| Index: src/preparser.cc
|
| diff --git a/src/preparser.cc b/src/preparser.cc
|
| index cd9e9fa36a49b6980c87beed00560697a6a04860..a5de23ebeede10d2b59726f32d0294f6403555f1 100644
|
| --- a/src/preparser.cc
|
| +++ b/src/preparser.cc
|
| @@ -42,7 +42,7 @@
|
| #include "unicode.h"
|
| #include "utils.h"
|
|
|
| -#if V8_CC_MSVC && (_MSC_VER < 1800)
|
| +#if V8_LIBC_MSVCRT && (_MSC_VER < 1800)
|
| namespace std {
|
|
|
| // Usually defined in math.h, but not in MSVC until VS2013+.
|
| @@ -55,14 +55,99 @@ int isfinite(double value);
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +void PreParserTraits::ReportMessageAt(Scanner::Location location,
|
| + const char* message,
|
| + Vector<const char*> args) {
|
| + ReportMessageAt(location.beg_pos,
|
| + location.end_pos,
|
| + message,
|
| + args.length() > 0 ? args[0] : NULL);
|
| +}
|
| +
|
| +
|
| +void PreParserTraits::ReportMessageAt(Scanner::Location location,
|
| + const char* type,
|
| + const char* name_opt) {
|
| + pre_parser_->log_
|
| + ->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
|
| +}
|
| +
|
| +
|
| +void PreParserTraits::ReportMessageAt(int start_pos,
|
| + int end_pos,
|
| + const char* type,
|
| + const char* name_opt) {
|
| + pre_parser_->log_->LogMessage(start_pos, end_pos, type, name_opt);
|
| +}
|
| +
|
| +
|
| +PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
|
| + pre_parser_->LogSymbol();
|
| + if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
|
| + return PreParserIdentifier::FutureReserved();
|
| + } else if (scanner->current_token() ==
|
| + Token::FUTURE_STRICT_RESERVED_WORD) {
|
| + return PreParserIdentifier::FutureStrictReserved();
|
| + } else if (scanner->current_token() == Token::YIELD) {
|
| + return PreParserIdentifier::Yield();
|
| + }
|
| + if (scanner->is_literal_ascii()) {
|
| + // Detect strict-mode poison words.
|
| + if (scanner->literal_length() == 4 &&
|
| + !strncmp(scanner->literal_ascii_string().start(), "eval", 4)) {
|
| + return PreParserIdentifier::Eval();
|
| + }
|
| + if (scanner->literal_length() == 9 &&
|
| + !strncmp(scanner->literal_ascii_string().start(), "arguments", 9)) {
|
| + return PreParserIdentifier::Arguments();
|
| + }
|
| + }
|
| + return PreParserIdentifier::Default();
|
| +}
|
| +
|
| +
|
| +PreParserExpression PreParserTraits::ExpressionFromString(
|
| + int pos, Scanner* scanner, PreParserFactory* factory) {
|
| + const int kUseStrictLength = 10;
|
| + const char* kUseStrictChars = "use strict";
|
| + pre_parser_->LogSymbol();
|
| + if (scanner->is_literal_ascii() &&
|
| + scanner->literal_length() == kUseStrictLength &&
|
| + !scanner->literal_contains_escapes() &&
|
| + !strncmp(scanner->literal_ascii_string().start(), kUseStrictChars,
|
| + kUseStrictLength)) {
|
| + return PreParserExpression::UseStrictStringLiteral();
|
| + }
|
| + return PreParserExpression::StringLiteral();
|
| +}
|
| +
|
| +
|
| +PreParserExpression PreParserTraits::ParseObjectLiteral(bool* ok) {
|
| + return pre_parser_->ParseObjectLiteral(ok);
|
| +}
|
| +
|
| +
|
| +PreParserExpression PreParserTraits::ParseAssignmentExpression(bool accept_IN,
|
| + bool* ok) {
|
| + return pre_parser_->ParseAssignmentExpression(accept_IN, ok);
|
| +}
|
| +
|
| +
|
| +PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
|
| + return pre_parser_->ParseV8Intrinsic(ok);
|
| +}
|
| +
|
| +
|
| PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
| LanguageMode mode, bool is_generator, ParserRecorder* log) {
|
| log_ = log;
|
| // Lazy functions always have trivial outer scopes (no with/catch scopes).
|
| - Scope top_scope(&scope_, kTopLevelScope);
|
| - set_language_mode(mode);
|
| - Scope function_scope(&scope_, kFunctionScope);
|
| - function_scope.set_is_generator(is_generator);
|
| + PreParserScope top_scope(scope_, GLOBAL_SCOPE);
|
| + FunctionState top_state(&function_state_, &scope_, &top_scope);
|
| + scope_->SetLanguageMode(mode);
|
| + PreParserScope function_scope(scope_, FUNCTION_SCOPE);
|
| + FunctionState function_state(&function_state_, &scope_, &function_scope);
|
| + function_state.set_is_generator(is_generator);
|
| ASSERT_EQ(Token::LBRACE, scanner()->current_token());
|
| bool ok = true;
|
| int start_position = peek_position();
|
| @@ -72,12 +157,9 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
| ReportUnexpectedToken(scanner()->current_token());
|
| } else {
|
| ASSERT_EQ(Token::RBRACE, scanner()->peek());
|
| - if (!is_classic_mode()) {
|
| + if (!scope_->is_classic_mode()) {
|
| int end_pos = scanner()->location().end_pos;
|
| CheckOctalLiteral(start_position, end_pos, &ok);
|
| - if (ok) {
|
| - CheckDelayedStrictModeViolation(start_position, end_pos, &ok);
|
| - }
|
| }
|
| }
|
| return kPreParseSuccess;
|
| @@ -97,37 +179,6 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
| // That means that contextual checks (like a label being declared where
|
| // it is used) are generally omitted.
|
|
|
| -void PreParser::ReportUnexpectedToken(Token::Value token) {
|
| - // We don't report stack overflows here, to avoid increasing the
|
| - // stack depth even further. Instead we report it after parsing is
|
| - // over, in ParseProgram.
|
| - if (token == Token::ILLEGAL && stack_overflow()) {
|
| - return;
|
| - }
|
| - ScannerBase::Location source_location = scanner()->location();
|
| -
|
| - // Four of the tokens are treated specially
|
| - switch (token) {
|
| - case Token::EOS:
|
| - return ReportMessageAt(source_location, "unexpected_eos", NULL);
|
| - case Token::NUMBER:
|
| - return ReportMessageAt(source_location, "unexpected_token_number", NULL);
|
| - case Token::STRING:
|
| - return ReportMessageAt(source_location, "unexpected_token_string", NULL);
|
| - case Token::IDENTIFIER:
|
| - return ReportMessageAt(source_location,
|
| - "unexpected_token_identifier", NULL);
|
| - case Token::FUTURE_RESERVED_WORD:
|
| - return ReportMessageAt(source_location, "unexpected_reserved", NULL);
|
| - case Token::FUTURE_STRICT_RESERVED_WORD:
|
| - return ReportMessageAt(source_location,
|
| - "unexpected_strict_reserved", NULL);
|
| - default:
|
| - const char* name = Token::String(token);
|
| - ReportMessageAt(source_location, "unexpected_token", name);
|
| - }
|
| -}
|
| -
|
|
|
| #define CHECK_OK ok); \
|
| if (!*ok) return kUnknownSourceElements; \
|
| @@ -165,15 +216,18 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
|
| // SourceElements ::
|
| // (Statement)* <end_token>
|
|
|
| - bool allow_directive_prologue = true;
|
| + bool directive_prologue = true;
|
| while (peek() != end_token) {
|
| + if (directive_prologue && peek() != Token::STRING) {
|
| + directive_prologue = false;
|
| + }
|
| Statement statement = ParseSourceElement(CHECK_OK);
|
| - if (allow_directive_prologue) {
|
| + if (directive_prologue) {
|
| if (statement.IsUseStrictLiteral()) {
|
| - set_language_mode(allow_harmony_scoping() ?
|
| - EXTENDED_MODE : STRICT_MODE);
|
| + scope_->SetLanguageMode(allow_harmony_scoping() ?
|
| + EXTENDED_MODE : STRICT_MODE);
|
| } else if (!statement.IsStringLiteral()) {
|
| - allow_directive_prologue = false;
|
| + directive_prologue = false;
|
| }
|
| }
|
| }
|
| @@ -262,12 +316,14 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) {
|
| return ParseTryStatement(ok);
|
|
|
| case Token::FUNCTION: {
|
| - ScannerBase::Location start_location = scanner()->peek_location();
|
| + Scanner::Location start_location = scanner()->peek_location();
|
| Statement statement = ParseFunctionDeclaration(CHECK_OK);
|
| - ScannerBase::Location end_location = scanner()->location();
|
| - if (!is_classic_mode()) {
|
| - ReportMessageAt(start_location.beg_pos, end_location.end_pos,
|
| - "strict_function", NULL);
|
| + Scanner::Location end_location = scanner()->location();
|
| + if (!scope_->is_classic_mode()) {
|
| + PreParserTraits::ReportMessageAt(start_location.beg_pos,
|
| + end_location.end_pos,
|
| + "strict_function",
|
| + NULL);
|
| *ok = false;
|
| return Statement::Default();
|
| } else {
|
| @@ -293,22 +349,14 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
|
| Expect(Token::FUNCTION, CHECK_OK);
|
|
|
| bool is_generator = allow_generators() && Check(Token::MUL);
|
| - Identifier identifier = ParseIdentifier(CHECK_OK);
|
| - ScannerBase::Location location = scanner()->location();
|
| -
|
| - Expression function_value = ParseFunctionLiteral(is_generator, CHECK_OK);
|
| -
|
| - if (function_value.IsStrictFunction() &&
|
| - !identifier.IsValidStrictVariable()) {
|
| - // Strict mode violation, using either reserved word or eval/arguments
|
| - // as name of strict function.
|
| - const char* type = "strict_function_name";
|
| - if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
|
| - type = "strict_reserved_word";
|
| - }
|
| - ReportMessageAt(location, type, NULL);
|
| - *ok = false;
|
| - }
|
| + bool is_strict_reserved = false;
|
| + Identifier name = ParseIdentifierOrStrictReservedWord(
|
| + &is_strict_reserved, CHECK_OK);
|
| + ParseFunctionLiteral(name,
|
| + scanner()->location(),
|
| + is_strict_reserved,
|
| + is_generator,
|
| + CHECK_OK);
|
| return Statement::FunctionDeclaration();
|
| }
|
|
|
| @@ -322,7 +370,7 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
|
| //
|
| Expect(Token::LBRACE, CHECK_OK);
|
| while (peek() != Token::RBRACE) {
|
| - if (is_extended_mode()) {
|
| + if (scope_->is_extended_mode()) {
|
| ParseSourceElement(CHECK_OK);
|
| } else {
|
| ParseStatement(CHECK_OK);
|
| @@ -386,21 +434,19 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
|
| // existing pages. Therefore we keep allowing const with the old
|
| // non-harmony semantics in classic mode.
|
| Consume(Token::CONST);
|
| - switch (language_mode()) {
|
| + switch (scope_->language_mode()) {
|
| case CLASSIC_MODE:
|
| break;
|
| case STRICT_MODE: {
|
| - ScannerBase::Location location = scanner()->peek_location();
|
| - ReportMessageAt(location, "strict_const", NULL);
|
| + Scanner::Location location = scanner()->peek_location();
|
| + ReportMessageAt(location, "strict_const");
|
| *ok = false;
|
| return Statement::Default();
|
| }
|
| case EXTENDED_MODE:
|
| if (var_context != kSourceElement &&
|
| var_context != kForStatement) {
|
| - ScannerBase::Location location = scanner()->peek_location();
|
| - ReportMessageAt(location.beg_pos, location.end_pos,
|
| - "unprotected_const", NULL);
|
| + ReportMessageAt(scanner()->peek_location(), "unprotected_const");
|
| *ok = false;
|
| return Statement::Default();
|
| }
|
| @@ -414,19 +460,15 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
|
| //
|
| // * It is a Syntax Error if the code that matches this production is not
|
| // contained in extended code.
|
| - if (!is_extended_mode()) {
|
| - ScannerBase::Location location = scanner()->peek_location();
|
| - ReportMessageAt(location.beg_pos, location.end_pos,
|
| - "illegal_let", NULL);
|
| + if (!scope_->is_extended_mode()) {
|
| + ReportMessageAt(scanner()->peek_location(), "illegal_let");
|
| *ok = false;
|
| return Statement::Default();
|
| }
|
| Consume(Token::LET);
|
| if (var_context != kSourceElement &&
|
| var_context != kForStatement) {
|
| - ScannerBase::Location location = scanner()->peek_location();
|
| - ReportMessageAt(location.beg_pos, location.end_pos,
|
| - "unprotected_let", NULL);
|
| + ReportMessageAt(scanner()->peek_location(), "unprotected_let");
|
| *ok = false;
|
| return Statement::Default();
|
| }
|
| @@ -443,14 +485,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
|
| do {
|
| // Parse variable name.
|
| if (nvars > 0) Consume(Token::COMMA);
|
| - Identifier identifier = ParseIdentifier(CHECK_OK);
|
| - if (!is_classic_mode() && !identifier.IsValidStrictVariable()) {
|
| - StrictModeIdentifierViolation(scanner()->location(),
|
| - "strict_var_name",
|
| - identifier,
|
| - ok);
|
| - return Statement::Default();
|
| - }
|
| + ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| nvars++;
|
| if (peek() == Token::ASSIGN || require_initializer) {
|
| Expect(Token::ASSIGN, CHECK_OK);
|
| @@ -469,16 +504,20 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
|
| // Expression ';'
|
| // Identifier ':' Statement
|
|
|
| + bool starts_with_identifier = peek_any_identifier();
|
| Expression expr = ParseExpression(true, CHECK_OK);
|
| - if (expr.IsRawIdentifier()) {
|
| + // Even if the expression starts with an identifier, it is not necessarily an
|
| + // identifier. For example, "foo + bar" starts with an identifier but is not
|
| + // an identifier.
|
| + 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(is_classic_mode() ||
|
| + ASSERT(scope_->is_classic_mode() ||
|
| (!expr.AsIdentifier().IsFutureStrictReserved() &&
|
| !expr.AsIdentifier().IsYield()));
|
| - if (peek() == Token::COLON) {
|
| - Consume(Token::COLON);
|
| - return ParseStatement(ok);
|
| - }
|
| + Consume(Token::COLON);
|
| + return ParseStatement(ok);
|
| // Preparsing is disabled for extensions (because the extension details
|
| // aren't passed to lazily compiled functions), so we don't
|
| // accept "native function" in the preparser.
|
| @@ -516,7 +555,8 @@ PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
|
| tok != Token::SEMICOLON &&
|
| tok != Token::RBRACE &&
|
| tok != Token::EOS) {
|
| - ParseIdentifier(CHECK_OK);
|
| + // ECMA allows "eval" or "arguments" as labels even in strict mode.
|
| + ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| }
|
| ExpectSemicolon(CHECK_OK);
|
| return Statement::Default();
|
| @@ -533,7 +573,8 @@ PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
|
| tok != Token::SEMICOLON &&
|
| tok != Token::RBRACE &&
|
| tok != Token::EOS) {
|
| - ParseIdentifier(CHECK_OK);
|
| + // ECMA allows "eval" or "arguments" as labels even in strict mode.
|
| + ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| }
|
| ExpectSemicolon(CHECK_OK);
|
| return Statement::Default();
|
| @@ -570,9 +611,8 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
|
| // WithStatement ::
|
| // 'with' '(' Expression ')' Statement
|
| Expect(Token::WITH, CHECK_OK);
|
| - if (!is_classic_mode()) {
|
| - ScannerBase::Location location = scanner()->location();
|
| - ReportMessageAt(location, "strict_mode_with", NULL);
|
| + if (!scope_->is_classic_mode()) {
|
| + ReportMessageAt(scanner()->location(), "strict_mode_with");
|
| *ok = false;
|
| return Statement::Default();
|
| }
|
| @@ -580,7 +620,8 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
|
| ParseExpression(true, CHECK_OK);
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| - Scope::InsideWith iw(scope_);
|
| + PreParserScope with_scope(scope_, WITH_SCOPE);
|
| + BlockState block_state(&scope_, &with_scope);
|
| ParseStatement(CHECK_OK);
|
| return Statement::Default();
|
| }
|
| @@ -716,8 +757,7 @@ PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
|
|
|
| Expect(Token::THROW, CHECK_OK);
|
| if (scanner()->HasAnyLineTerminatorBeforeNext()) {
|
| - ScannerBase::Location pos = scanner()->location();
|
| - ReportMessageAt(pos, "newline_after_throw", NULL);
|
| + ReportMessageAt(scanner()->location(), "newline_after_throw");
|
| *ok = false;
|
| return Statement::Default();
|
| }
|
| @@ -739,38 +779,31 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
|
| // Finally ::
|
| // 'finally' Block
|
|
|
| - // In preparsing, allow any number of catch/finally blocks, including zero
|
| - // of both.
|
| -
|
| Expect(Token::TRY, CHECK_OK);
|
|
|
| ParseBlock(CHECK_OK);
|
|
|
| - bool catch_or_finally_seen = false;
|
| - if (peek() == Token::CATCH) {
|
| + Token::Value tok = peek();
|
| + if (tok != Token::CATCH && tok != Token::FINALLY) {
|
| + ReportMessageAt(scanner()->location(), "no_catch_or_finally");
|
| + *ok = false;
|
| + return Statement::Default();
|
| + }
|
| + if (tok == Token::CATCH) {
|
| Consume(Token::CATCH);
|
| Expect(Token::LPAREN, CHECK_OK);
|
| - Identifier id = ParseIdentifier(CHECK_OK);
|
| - if (!is_classic_mode() && !id.IsValidStrictVariable()) {
|
| - StrictModeIdentifierViolation(scanner()->location(),
|
| - "strict_catch_variable",
|
| - id,
|
| - ok);
|
| - return Statement::Default();
|
| - }
|
| + ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| Expect(Token::RPAREN, CHECK_OK);
|
| - { Scope::InsideWith iw(scope_);
|
| + {
|
| + PreParserScope with_scope(scope_, WITH_SCOPE);
|
| + BlockState block_state(&scope_, &with_scope);
|
| ParseBlock(CHECK_OK);
|
| }
|
| - catch_or_finally_seen = true;
|
| + tok = peek();
|
| }
|
| - if (peek() == Token::FINALLY) {
|
| + if (tok == Token::FINALLY) {
|
| Consume(Token::FINALLY);
|
| ParseBlock(CHECK_OK);
|
| - catch_or_finally_seen = true;
|
| - }
|
| - if (!catch_or_finally_seen) {
|
| - *ok = false;
|
| }
|
| return Statement::Default();
|
| }
|
| @@ -797,22 +830,6 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
|
| #undef DUMMY
|
|
|
|
|
| -// Precedence = 1
|
| -PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
|
| - // Expression ::
|
| - // AssignmentExpression
|
| - // Expression ',' AssignmentExpression
|
| -
|
| - Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
|
| - while (peek() == Token::COMMA) {
|
| - Expect(Token::COMMA, CHECK_OK);
|
| - ParseAssignmentExpression(accept_IN, CHECK_OK);
|
| - result = Expression::Default();
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -
|
| // Precedence = 2
|
| PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
|
| bool* ok) {
|
| @@ -821,11 +838,11 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
|
| // YieldExpression
|
| // LeftHandSideExpression AssignmentOperator AssignmentExpression
|
|
|
| - if (scope_->is_generator() && peek() == Token::YIELD) {
|
| + if (function_state_->is_generator() && peek() == Token::YIELD) {
|
| return ParseYieldExpression(ok);
|
| }
|
|
|
| - ScannerBase::Location before = scanner()->peek_location();
|
| + Scanner::Location before = scanner()->peek_location();
|
| Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
|
|
|
| if (!Token::IsAssignmentOp(peek())) {
|
| @@ -833,12 +850,12 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
|
| return expression;
|
| }
|
|
|
| - if (!is_classic_mode() &&
|
| + if (!scope_->is_classic_mode() &&
|
| expression.IsIdentifier() &&
|
| expression.AsIdentifier().IsEvalOrArguments()) {
|
| - ScannerBase::Location after = scanner()->location();
|
| - ReportMessageAt(before.beg_pos, after.end_pos,
|
| - "strict_lhs_assignment", NULL);
|
| + Scanner::Location after = scanner()->location();
|
| + PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos,
|
| + "strict_eval_arguments", NULL);
|
| *ok = false;
|
| return Expression::Default();
|
| }
|
| @@ -847,7 +864,7 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
|
| ParseAssignmentExpression(accept_IN, CHECK_OK);
|
|
|
| if ((op == Token::ASSIGN) && expression.IsThisProperty()) {
|
| - scope_->AddProperty();
|
| + function_state_->AddProperty();
|
| }
|
|
|
| return Expression::Default();
|
| @@ -925,14 +942,14 @@ PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
|
| return Expression::Default();
|
| } else if (Token::IsCountOp(op)) {
|
| op = Next();
|
| - ScannerBase::Location before = scanner()->peek_location();
|
| + Scanner::Location before = scanner()->peek_location();
|
| Expression expression = ParseUnaryExpression(CHECK_OK);
|
| - if (!is_classic_mode() &&
|
| + if (!scope_->is_classic_mode() &&
|
| expression.IsIdentifier() &&
|
| expression.AsIdentifier().IsEvalOrArguments()) {
|
| - ScannerBase::Location after = scanner()->location();
|
| - ReportMessageAt(before.beg_pos, after.end_pos,
|
| - "strict_lhs_prefix", NULL);
|
| + Scanner::Location after = scanner()->location();
|
| + PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos,
|
| + "strict_eval_arguments", NULL);
|
| *ok = false;
|
| }
|
| return Expression::Default();
|
| @@ -946,16 +963,16 @@ PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
|
| // PostfixExpression ::
|
| // LeftHandSideExpression ('++' | '--')?
|
|
|
| - ScannerBase::Location before = scanner()->peek_location();
|
| + Scanner::Location before = scanner()->peek_location();
|
| Expression expression = ParseLeftHandSideExpression(CHECK_OK);
|
| if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
|
| Token::IsCountOp(peek())) {
|
| - if (!is_classic_mode() &&
|
| + if (!scope_->is_classic_mode() &&
|
| expression.IsIdentifier() &&
|
| expression.AsIdentifier().IsEvalOrArguments()) {
|
| - ScannerBase::Location after = scanner()->location();
|
| - ReportMessageAt(before.beg_pos, after.end_pos,
|
| - "strict_lhs_postfix", NULL);
|
| + Scanner::Location after = scanner()->location();
|
| + PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos,
|
| + "strict_eval_arguments", NULL);
|
| *ok = false;
|
| return Expression::Default();
|
| }
|
| @@ -970,12 +987,7 @@ PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
|
| // LeftHandSideExpression ::
|
| // (NewExpression | MemberExpression) ...
|
|
|
| - Expression result = Expression::Default();
|
| - if (peek() == Token::NEW) {
|
| - result = ParseNewExpression(CHECK_OK);
|
| - } else {
|
| - result = ParseMemberExpression(CHECK_OK);
|
| - }
|
| + Expression result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
|
|
|
| while (true) {
|
| switch (peek()) {
|
| @@ -1015,198 +1027,98 @@ PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
|
| }
|
|
|
|
|
| -PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
|
| +PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
|
| + bool* ok) {
|
| // NewExpression ::
|
| // ('new')+ MemberExpression
|
|
|
| - // The grammar for new expressions is pretty warped. The keyword
|
| - // 'new' can either be a part of the new expression (where it isn't
|
| - // followed by an argument list) or a part of the member expression,
|
| - // where it must be followed by an argument list. To accommodate
|
| - // this, we parse the 'new' keywords greedily and keep track of how
|
| - // many we have parsed. This information is then passed on to the
|
| - // member expression parser, which is only allowed to match argument
|
| - // lists as long as it has 'new' prefixes left
|
| - unsigned new_count = 0;
|
| - do {
|
| - Consume(Token::NEW);
|
| - new_count++;
|
| - } while (peek() == Token::NEW);
|
| + // See Parser::ParseNewExpression.
|
|
|
| - return ParseMemberWithNewPrefixesExpression(new_count, ok);
|
| + if (peek() == Token::NEW) {
|
| + Consume(Token::NEW);
|
| + ParseMemberWithNewPrefixesExpression(CHECK_OK);
|
| + if (peek() == Token::LPAREN) {
|
| + // NewExpression with arguments.
|
| + ParseArguments(CHECK_OK);
|
| + // The expression can still continue with . or [ after the arguments.
|
| + ParseMemberExpressionContinuation(Expression::Default(), CHECK_OK);
|
| + }
|
| + return Expression::Default();
|
| + }
|
| + // No 'new' keyword.
|
| + return ParseMemberExpression(ok);
|
| }
|
|
|
|
|
| PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
|
| - return ParseMemberWithNewPrefixesExpression(0, ok);
|
| -}
|
| -
|
| -
|
| -PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
|
| - unsigned new_count, bool* ok) {
|
| // MemberExpression ::
|
| // (PrimaryExpression | FunctionLiteral)
|
| // ('[' Expression ']' | '.' Identifier | Arguments)*
|
|
|
| + // The '[' Expression ']' and '.' Identifier parts are parsed by
|
| + // ParseMemberExpressionContinuation, and the Arguments part is parsed by the
|
| + // caller.
|
| +
|
| // Parse the initial primary or function expression.
|
| Expression result = Expression::Default();
|
| if (peek() == Token::FUNCTION) {
|
| Consume(Token::FUNCTION);
|
|
|
| bool is_generator = allow_generators() && Check(Token::MUL);
|
| - Identifier identifier = Identifier::Default();
|
| + Identifier name = Identifier::Default();
|
| + bool is_strict_reserved_name = false;
|
| + Scanner::Location function_name_location = Scanner::Location::invalid();
|
| if (peek_any_identifier()) {
|
| - identifier = ParseIdentifier(CHECK_OK);
|
| - }
|
| - result = ParseFunctionLiteral(is_generator, CHECK_OK);
|
| - if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
|
| - StrictModeIdentifierViolation(scanner()->location(),
|
| - "strict_function_name",
|
| - identifier,
|
| - ok);
|
| - return Expression::Default();
|
| + name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
|
| + CHECK_OK);
|
| + function_name_location = scanner()->location();
|
| }
|
| + result = ParseFunctionLiteral(name,
|
| + function_name_location,
|
| + is_strict_reserved_name,
|
| + is_generator,
|
| + CHECK_OK);
|
| } else {
|
| result = ParsePrimaryExpression(CHECK_OK);
|
| }
|
| + result = ParseMemberExpressionContinuation(result, CHECK_OK);
|
| + return result;
|
| +}
|
| +
|
|
|
| +PreParser::Expression PreParser::ParseMemberExpressionContinuation(
|
| + PreParserExpression expression, bool* ok) {
|
| + // Parses this part of MemberExpression:
|
| + // ('[' Expression ']' | '.' Identifier)*
|
| while (true) {
|
| switch (peek()) {
|
| case Token::LBRACK: {
|
| Consume(Token::LBRACK);
|
| ParseExpression(true, CHECK_OK);
|
| Expect(Token::RBRACK, CHECK_OK);
|
| - if (result.IsThis()) {
|
| - result = Expression::ThisProperty();
|
| + if (expression.IsThis()) {
|
| + expression = Expression::ThisProperty();
|
| } else {
|
| - result = Expression::Default();
|
| + expression = Expression::Default();
|
| }
|
| break;
|
| }
|
| case Token::PERIOD: {
|
| Consume(Token::PERIOD);
|
| ParseIdentifierName(CHECK_OK);
|
| - if (result.IsThis()) {
|
| - result = Expression::ThisProperty();
|
| + if (expression.IsThis()) {
|
| + expression = Expression::ThisProperty();
|
| } else {
|
| - result = Expression::Default();
|
| + expression = Expression::Default();
|
| }
|
| break;
|
| }
|
| - case Token::LPAREN: {
|
| - if (new_count == 0) return result;
|
| - // Consume one of the new prefixes (already parsed).
|
| - ParseArguments(CHECK_OK);
|
| - new_count--;
|
| - result = Expression::Default();
|
| - break;
|
| - }
|
| default:
|
| - return result;
|
| + return expression;
|
| }
|
| }
|
| -}
|
| -
|
| -
|
| -PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
|
| - // PrimaryExpression ::
|
| - // 'this'
|
| - // 'null'
|
| - // 'true'
|
| - // 'false'
|
| - // Identifier
|
| - // Number
|
| - // String
|
| - // ArrayLiteral
|
| - // ObjectLiteral
|
| - // RegExpLiteral
|
| - // '(' Expression ')'
|
| -
|
| - Expression result = Expression::Default();
|
| - switch (peek()) {
|
| - case Token::THIS: {
|
| - Next();
|
| - result = Expression::This();
|
| - break;
|
| - }
|
| -
|
| - case Token::FUTURE_RESERVED_WORD:
|
| - case Token::FUTURE_STRICT_RESERVED_WORD:
|
| - case Token::YIELD:
|
| - case Token::IDENTIFIER: {
|
| - Identifier id = ParseIdentifier(CHECK_OK);
|
| - result = Expression::FromIdentifier(id);
|
| - break;
|
| - }
|
| -
|
| - case Token::NULL_LITERAL:
|
| - case Token::TRUE_LITERAL:
|
| - case Token::FALSE_LITERAL:
|
| - case Token::NUMBER: {
|
| - Next();
|
| - break;
|
| - }
|
| - case Token::STRING: {
|
| - Next();
|
| - result = GetStringSymbol();
|
| - break;
|
| - }
|
| -
|
| - case Token::ASSIGN_DIV:
|
| - result = ParseRegExpLiteral(true, CHECK_OK);
|
| - break;
|
| -
|
| - case Token::DIV:
|
| - result = ParseRegExpLiteral(false, CHECK_OK);
|
| - break;
|
| -
|
| - case Token::LBRACK:
|
| - result = ParseArrayLiteral(CHECK_OK);
|
| - break;
|
| -
|
| - case Token::LBRACE:
|
| - result = ParseObjectLiteral(CHECK_OK);
|
| - break;
|
| -
|
| - case Token::LPAREN:
|
| - Consume(Token::LPAREN);
|
| - parenthesized_function_ = (peek() == Token::FUNCTION);
|
| - result = ParseExpression(true, CHECK_OK);
|
| - Expect(Token::RPAREN, CHECK_OK);
|
| - result = result.Parenthesize();
|
| - break;
|
| -
|
| - case Token::MOD:
|
| - result = ParseV8Intrinsic(CHECK_OK);
|
| - break;
|
| -
|
| - default: {
|
| - Next();
|
| - *ok = false;
|
| - return Expression::Default();
|
| - }
|
| - }
|
| -
|
| - return result;
|
| -}
|
| -
|
| -
|
| -PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
|
| - // ArrayLiteral ::
|
| - // '[' Expression? (',' Expression?)* ']'
|
| - Expect(Token::LBRACK, CHECK_OK);
|
| - while (peek() != Token::RBRACK) {
|
| - if (peek() != Token::COMMA) {
|
| - ParseAssignmentExpression(true, CHECK_OK);
|
| - }
|
| - if (peek() != Token::RBRACK) {
|
| - Expect(Token::COMMA, CHECK_OK);
|
| - }
|
| - }
|
| - Expect(Token::RBRACK, CHECK_OK);
|
| -
|
| - scope_->NextMaterializedLiteralIndex();
|
| - return Expression::Default();
|
| + ASSERT(false);
|
| + return PreParserExpression::Default();
|
| }
|
|
|
|
|
| @@ -1217,7 +1129,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
|
| // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
|
| // )*[','] '}'
|
|
|
| - ObjectLiteralChecker checker(this, language_mode());
|
| + ObjectLiteralChecker checker(this, scope_->language_mode());
|
|
|
| Expect(Token::LBRACE, CHECK_OK);
|
| while (peek() != Token::RBRACE) {
|
| @@ -1246,7 +1158,11 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
|
| }
|
| PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
|
| checker.CheckProperty(name, type, CHECK_OK);
|
| - ParseFunctionLiteral(false, CHECK_OK);
|
| + ParseFunctionLiteral(Identifier::Default(),
|
| + scanner()->location(),
|
| + false, // reserved words are allowed here
|
| + false, // not a generator
|
| + CHECK_OK);
|
| if (peek() != Token::RBRACE) {
|
| Expect(Token::COMMA, CHECK_OK);
|
| }
|
| @@ -1258,7 +1174,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
|
| case Token::STRING:
|
| Consume(next);
|
| checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
| - GetStringSymbol();
|
| + LogSymbol();
|
| break;
|
| case Token::NUMBER:
|
| Consume(next);
|
| @@ -1268,6 +1184,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
|
| if (Token::IsKeyword(next)) {
|
| Consume(next);
|
| checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
| + LogSymbol();
|
| } else {
|
| // Unexpected token.
|
| *ok = false;
|
| @@ -1283,29 +1200,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
|
| }
|
| Expect(Token::RBRACE, CHECK_OK);
|
|
|
| - scope_->NextMaterializedLiteralIndex();
|
| - return Expression::Default();
|
| -}
|
| -
|
| -
|
| -PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
|
| - bool* ok) {
|
| - if (!scanner()->ScanRegExpPattern(seen_equal)) {
|
| - Next();
|
| - ReportMessageAt(scanner()->location(), "unterminated_regexp", NULL);
|
| - *ok = false;
|
| - return Expression::Default();
|
| - }
|
| -
|
| - scope_->NextMaterializedLiteralIndex();
|
| -
|
| - if (!scanner()->ScanRegExpFlags()) {
|
| - Next();
|
| - ReportMessageAt(scanner()->location(), "invalid_regexp_flags", NULL);
|
| - *ok = false;
|
| - return Expression::Default();
|
| - }
|
| - Next();
|
| + function_state_->NextMaterializedLiteralIndex();
|
| return Expression::Default();
|
| }
|
|
|
| @@ -1332,31 +1227,44 @@ PreParser::Arguments PreParser::ParseArguments(bool* ok) {
|
| return argc;
|
| }
|
|
|
| -
|
| -PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator,
|
| - bool* ok) {
|
| +PreParser::Expression PreParser::ParseFunctionLiteral(
|
| + Identifier function_name,
|
| + Scanner::Location function_name_location,
|
| + bool name_is_strict_reserved,
|
| + bool is_generator,
|
| + bool* ok) {
|
| // Function ::
|
| // '(' FormalParameterList? ')' '{' FunctionBody '}'
|
|
|
| // Parse function body.
|
| ScopeType outer_scope_type = scope_->type();
|
| - bool inside_with = scope_->IsInsideWith();
|
| - Scope function_scope(&scope_, kFunctionScope);
|
| - function_scope.set_is_generator(is_generator);
|
| + bool inside_with = scope_->inside_with();
|
| + PreParserScope function_scope(scope_, FUNCTION_SCOPE);
|
| + FunctionState function_state(&function_state_, &scope_, &function_scope);
|
| + function_state.set_is_generator(is_generator);
|
| // 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
|
| + // locations of these errors if they occur and produce the errors later.
|
| + 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();
|
| while (!done) {
|
| - Identifier id = ParseIdentifier(CHECK_OK);
|
| - if (!id.IsValidStrictVariable()) {
|
| - StrictModeIdentifierViolation(scanner()->location(),
|
| - "strict_param_name",
|
| - id,
|
| - CHECK_OK);
|
| + bool is_strict_reserved = false;
|
| + Identifier param_name =
|
| + ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
|
| + if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) {
|
| + eval_args_error_loc = scanner()->location();
|
| }
|
| + if (!reserved_error_loc.IsValid() && is_strict_reserved) {
|
| + reserved_error_loc = scanner()->location();
|
| + }
|
| +
|
| int prev_value;
|
| if (scanner()->is_literal_ascii()) {
|
| prev_value =
|
| @@ -1366,11 +1274,10 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator,
|
| duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1);
|
| }
|
|
|
| - if (prev_value != 0) {
|
| - SetStrictModeViolation(scanner()->location(),
|
| - "strict_param_dupe",
|
| - CHECK_OK);
|
| + if (!dupe_error_loc.IsValid() && prev_value != 0) {
|
| + dupe_error_loc = scanner()->location();
|
| }
|
| +
|
| done = (peek() == Token::RPAREN);
|
| if (!done) {
|
| Expect(Token::COMMA, CHECK_OK);
|
| @@ -1378,26 +1285,52 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator,
|
| }
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| - // Determine if the function will be lazily compiled.
|
| - // Currently only happens to top-level functions.
|
| - // Optimistically assume that all top-level functions are lazily compiled.
|
| - bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
|
| - !inside_with && allow_lazy() &&
|
| - !parenthesized_function_);
|
| + // See Parser::ParseFunctionLiteral for more information about lazy parsing
|
| + // and lazy compilation.
|
| + bool is_lazily_parsed = (outer_scope_type == GLOBAL_SCOPE &&
|
| + !inside_with && allow_lazy() &&
|
| + !parenthesized_function_);
|
| parenthesized_function_ = false;
|
|
|
| Expect(Token::LBRACE, CHECK_OK);
|
| - if (is_lazily_compiled) {
|
| + if (is_lazily_parsed) {
|
| ParseLazyFunctionLiteralBody(CHECK_OK);
|
| } else {
|
| ParseSourceElements(Token::RBRACE, ok);
|
| }
|
| Expect(Token::RBRACE, CHECK_OK);
|
|
|
| - if (!is_classic_mode()) {
|
| + // Validate strict mode. We can do this only after parsing the function,
|
| + // since the function can declare itself strict.
|
| + if (!scope_->is_classic_mode()) {
|
| + if (function_name.IsEvalOrArguments()) {
|
| + ReportMessageAt(function_name_location, "strict_eval_arguments");
|
| + *ok = false;
|
| + return Expression::Default();
|
| + }
|
| + if (name_is_strict_reserved) {
|
| + ReportMessageAt(function_name_location, "unexpected_strict_reserved");
|
| + *ok = false;
|
| + return Expression::Default();
|
| + }
|
| + if (eval_args_error_loc.IsValid()) {
|
| + ReportMessageAt(eval_args_error_loc, "strict_eval_arguments");
|
| + *ok = false;
|
| + return Expression::Default();
|
| + }
|
| + if (dupe_error_loc.IsValid()) {
|
| + ReportMessageAt(dupe_error_loc, "strict_param_dupe");
|
| + *ok = false;
|
| + return Expression::Default();
|
| + }
|
| + if (reserved_error_loc.IsValid()) {
|
| + ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved");
|
| + *ok = false;
|
| + return Expression::Default();
|
| + }
|
| +
|
| int end_position = scanner()->location().end_pos;
|
| CheckOctalLiteral(start_position, end_position, CHECK_OK);
|
| - CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
|
| return Expression::StrictFunction();
|
| }
|
|
|
| @@ -1416,9 +1349,9 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
|
| ASSERT_EQ(Token::RBRACE, scanner()->peek());
|
| int body_end = scanner()->peek_location().end_pos;
|
| log_->LogFunction(body_start, body_end,
|
| - scope_->materialized_literal_count(),
|
| - scope_->expected_properties(),
|
| - language_mode());
|
| + function_state_->materialized_literal_count(),
|
| + function_state_->expected_property_count(),
|
| + scope_->language_mode());
|
| }
|
|
|
|
|
| @@ -1430,7 +1363,8 @@ PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
|
| *ok = false;
|
| return Expression::Default();
|
| }
|
| - ParseIdentifier(CHECK_OK);
|
| + // Allow "eval" or "arguments" for backward compatibility.
|
| + ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| ParseArguments(ok);
|
|
|
| return Expression::Default();
|
| @@ -1449,201 +1383,4 @@ void PreParser::LogSymbol() {
|
| }
|
|
|
|
|
| -PreParser::Expression PreParser::GetStringSymbol() {
|
| - const int kUseStrictLength = 10;
|
| - const char* kUseStrictChars = "use strict";
|
| - LogSymbol();
|
| - if (scanner()->is_literal_ascii() &&
|
| - scanner()->literal_length() == kUseStrictLength &&
|
| - !scanner()->literal_contains_escapes() &&
|
| - !strncmp(scanner()->literal_ascii_string().start(), kUseStrictChars,
|
| - kUseStrictLength)) {
|
| - return Expression::UseStrictStringLiteral();
|
| - }
|
| - return Expression::StringLiteral();
|
| -}
|
| -
|
| -
|
| -PreParser::Identifier PreParser::GetIdentifierSymbol() {
|
| - LogSymbol();
|
| - if (scanner()->current_token() == Token::FUTURE_RESERVED_WORD) {
|
| - return Identifier::FutureReserved();
|
| - } else if (scanner()->current_token() ==
|
| - Token::FUTURE_STRICT_RESERVED_WORD) {
|
| - return Identifier::FutureStrictReserved();
|
| - } else if (scanner()->current_token() == Token::YIELD) {
|
| - return Identifier::Yield();
|
| - }
|
| - if (scanner()->is_literal_ascii()) {
|
| - // Detect strict-mode poison words.
|
| - if (scanner()->literal_length() == 4 &&
|
| - !strncmp(scanner()->literal_ascii_string().start(), "eval", 4)) {
|
| - return Identifier::Eval();
|
| - }
|
| - if (scanner()->literal_length() == 9 &&
|
| - !strncmp(scanner()->literal_ascii_string().start(), "arguments", 9)) {
|
| - return Identifier::Arguments();
|
| - }
|
| - }
|
| - return Identifier::Default();
|
| -}
|
| -
|
| -
|
| -PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
|
| - Token::Value next = Next();
|
| - switch (next) {
|
| - case Token::FUTURE_RESERVED_WORD: {
|
| - ScannerBase::Location location = scanner()->location();
|
| - ReportMessageAt(location.beg_pos, location.end_pos,
|
| - "reserved_word", NULL);
|
| - *ok = false;
|
| - return GetIdentifierSymbol();
|
| - }
|
| - case Token::YIELD:
|
| - if (scope_->is_generator()) {
|
| - // 'yield' in a generator is only valid as part of a YieldExpression.
|
| - ReportMessageAt(scanner()->location(), "unexpected_token", "yield");
|
| - *ok = false;
|
| - return Identifier::Yield();
|
| - }
|
| - // FALLTHROUGH
|
| - case Token::FUTURE_STRICT_RESERVED_WORD:
|
| - if (!is_classic_mode()) {
|
| - ScannerBase::Location location = scanner()->location();
|
| - ReportMessageAt(location.beg_pos, location.end_pos,
|
| - "strict_reserved_word", NULL);
|
| - *ok = false;
|
| - }
|
| - // FALLTHROUGH
|
| - case Token::IDENTIFIER:
|
| - return GetIdentifierSymbol();
|
| - default:
|
| - *ok = false;
|
| - return Identifier::Default();
|
| - }
|
| -}
|
| -
|
| -
|
| -void PreParser::SetStrictModeViolation(ScannerBase::Location location,
|
| - const char* type,
|
| - bool* ok) {
|
| - if (!is_classic_mode()) {
|
| - ReportMessageAt(location, type, NULL);
|
| - *ok = false;
|
| - return;
|
| - }
|
| - // Delay report in case this later turns out to be strict code
|
| - // (i.e., for function names and parameters prior to a "use strict"
|
| - // directive).
|
| - // It's safe to overwrite an existing violation.
|
| - // It's either from a function that turned out to be non-strict,
|
| - // or it's in the current function (and we just need to report
|
| - // one error), or it's in a unclosed nesting function that wasn't
|
| - // strict (otherwise we would already be in strict mode).
|
| - strict_mode_violation_location_ = location;
|
| - strict_mode_violation_type_ = type;
|
| -}
|
| -
|
| -
|
| -void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
|
| - int end_pos,
|
| - bool* ok) {
|
| - ScannerBase::Location location = strict_mode_violation_location_;
|
| - if (location.IsValid() &&
|
| - location.beg_pos > beg_pos && location.end_pos < end_pos) {
|
| - ReportMessageAt(location, strict_mode_violation_type_, NULL);
|
| - *ok = false;
|
| - }
|
| -}
|
| -
|
| -
|
| -void PreParser::StrictModeIdentifierViolation(ScannerBase::Location location,
|
| - const char* eval_args_type,
|
| - Identifier identifier,
|
| - bool* ok) {
|
| - const char* type = eval_args_type;
|
| - if (identifier.IsFutureReserved()) {
|
| - type = "reserved_word";
|
| - } else if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
|
| - type = "strict_reserved_word";
|
| - }
|
| - if (!is_classic_mode()) {
|
| - ReportMessageAt(location, type, NULL);
|
| - *ok = false;
|
| - return;
|
| - }
|
| - strict_mode_violation_location_ = location;
|
| - strict_mode_violation_type_ = type;
|
| -}
|
| -
|
| -
|
| -PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
|
| - Token::Value next = Next();
|
| - if (Token::IsKeyword(next)) {
|
| - int pos = position();
|
| - const char* keyword = Token::String(next);
|
| - log_->LogAsciiSymbol(pos, Vector<const char>(keyword, StrLength(keyword)));
|
| - return Identifier::Default();
|
| - }
|
| - if (next == Token::IDENTIFIER ||
|
| - next == Token::FUTURE_RESERVED_WORD ||
|
| - next == Token::FUTURE_STRICT_RESERVED_WORD) {
|
| - return GetIdentifierSymbol();
|
| - }
|
| - *ok = false;
|
| - return Identifier::Default();
|
| -}
|
| -
|
| -#undef CHECK_OK
|
| -
|
| -
|
| -// This function reads an identifier and determines whether or not it
|
| -// is 'get' or 'set'.
|
| -PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
|
| - bool* is_set,
|
| - bool* ok) {
|
| - Identifier result = ParseIdentifierName(ok);
|
| - if (!*ok) return Identifier::Default();
|
| - if (scanner()->is_literal_ascii() &&
|
| - scanner()->literal_length() == 3) {
|
| - const char* token = scanner()->literal_ascii_string().start();
|
| - *is_get = strncmp(token, "get", 3) == 0;
|
| - *is_set = !*is_get && strncmp(token, "set", 3) == 0;
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -
|
| -void PreParser::ObjectLiteralChecker::CheckProperty(Token::Value property,
|
| - PropertyKind type,
|
| - bool* ok) {
|
| - int old;
|
| - if (property == Token::NUMBER) {
|
| - old = finder_.AddNumber(scanner()->literal_ascii_string(), type);
|
| - } else if (scanner()->is_literal_ascii()) {
|
| - old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type);
|
| - } else {
|
| - old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type);
|
| - }
|
| - PropertyKind old_type = static_cast<PropertyKind>(old);
|
| - if (HasConflict(old_type, type)) {
|
| - if (IsDataDataConflict(old_type, type)) {
|
| - // Both are data properties.
|
| - if (language_mode_ == CLASSIC_MODE) return;
|
| - parser()->ReportMessageAt(scanner()->location(),
|
| - "strict_duplicate_property");
|
| - } else if (IsDataAccessorConflict(old_type, type)) {
|
| - // Both a data and an accessor property with the same name.
|
| - parser()->ReportMessageAt(scanner()->location(),
|
| - "accessor_data_property");
|
| - } else {
|
| - ASSERT(IsAccessorAccessorConflict(old_type, type));
|
| - // Both accessors of the same type.
|
| - parser()->ReportMessageAt(scanner()->location(),
|
| - "accessor_get_set");
|
| - }
|
| - *ok = false;
|
| - }
|
| -}
|
| -
|
| } } // v8::internal
|
|
|