diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-06-29 17:26:51 +0200 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-06-29 17:26:51 +0200 |
commit | 33af2720f26c2b25bc7f75ce7eb454ff99db6d35 (patch) | |
tree | 9a38f0c96420edf503eebd6325dd8d2d8249f653 /deps/v8/src/preparser.cc | |
parent | 6afdca885adeeeed9eef8cbb01c3d97af0bc084d (diff) | |
download | node-33af2720f26c2b25bc7f75ce7eb454ff99db6d35.tar.gz |
Upgrade V8 to 3.4.8
Diffstat (limited to 'deps/v8/src/preparser.cc')
-rw-r--r-- | deps/v8/src/preparser.cc | 564 |
1 files changed, 411 insertions, 153 deletions
diff --git a/deps/v8/src/preparser.cc b/deps/v8/src/preparser.cc index 252e88f46..da83f96ae 100644 --- a/deps/v8/src/preparser.cc +++ b/deps/v8/src/preparser.cc @@ -1,5 +1,4 @@ - -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -33,7 +32,9 @@ #include "allocation.h" #include "utils.h" #include "list.h" + #include "scanner-base.h" +#include "preparse-data-format.h" #include "preparse-data.h" #include "preparser.h" @@ -55,13 +56,6 @@ namespace preparser { namespace i = ::v8::internal; -#define CHECK_OK ok); \ - if (!*ok) return -1; \ - ((void)0 -#define DUMMY ) // to make indentation work -#undef DUMMY - - void PreParser::ReportUnexpectedToken(i::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 @@ -83,9 +77,14 @@ void PreParser::ReportUnexpectedToken(i::Token::Value token) { return ReportMessageAt(source_location.beg_pos, source_location.end_pos, "unexpected_token_string", NULL); case i::Token::IDENTIFIER: - case i::Token::FUTURE_RESERVED_WORD: return ReportMessageAt(source_location.beg_pos, source_location.end_pos, "unexpected_token_identifier", NULL); + case i::Token::FUTURE_RESERVED_WORD: + return ReportMessageAt(source_location.beg_pos, source_location.end_pos, + "unexpected_reserved", NULL); + case i::Token::FUTURE_STRICT_RESERVED_WORD: + return ReportMessageAt(source_location.beg_pos, source_location.end_pos, + "unexpected_strict_reserved", NULL); default: const char* name = i::Token::String(token); ReportMessageAt(source_location.beg_pos, source_location.end_pos, @@ -94,18 +93,53 @@ void PreParser::ReportUnexpectedToken(i::Token::Value token) { } +// Checks whether octal literal last seen is between beg_pos and end_pos. +// If so, reports an error. +void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { + i::Scanner::Location octal = scanner_->octal_position(); + if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) { + ReportMessageAt(octal.beg_pos, octal.end_pos, "strict_octal_literal", NULL); + scanner_->clear_octal_position(); + *ok = false; + } +} + + +#define CHECK_OK ok); \ + if (!*ok) return kUnknownSourceElements; \ + ((void)0 +#define DUMMY ) // to make indentation work +#undef DUMMY + + PreParser::SourceElements PreParser::ParseSourceElements(int end_token, bool* ok) { // SourceElements :: // (Statement)* <end_token> + bool allow_directive_prologue = true; while (peek() != end_token) { - ParseStatement(CHECK_OK); + Statement statement = ParseStatement(CHECK_OK); + if (allow_directive_prologue) { + if (statement.IsUseStrictLiteral()) { + set_strict_mode(); + } else if (!statement.IsStringLiteral()) { + allow_directive_prologue = false; + } + } } return kUnknownSourceElements; } +#undef CHECK_OK +#define CHECK_OK ok); \ + if (!*ok) return Statement::Default(); \ + ((void)0 +#define DUMMY ) // to make indentation work +#undef DUMMY + + PreParser::Statement PreParser::ParseStatement(bool* ok) { // Statement :: // Block @@ -142,10 +176,10 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) { case i::Token::SEMICOLON: Next(); - return kUnknownStatement; + return Statement::Default(); case i::Token::IF: - return ParseIfStatement(ok); + return ParseIfStatement(ok); case i::Token::DO: return ParseDoWhileStatement(ok); @@ -180,9 +214,6 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) { case i::Token::FUNCTION: return ParseFunctionDeclaration(ok); - case i::Token::NATIVE: - return ParseNativeDeclaration(ok); - case i::Token::DEBUGGER: return ParseDebuggerStatement(ok); @@ -196,32 +227,24 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { // FunctionDeclaration :: // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' Expect(i::Token::FUNCTION, CHECK_OK); - ParseIdentifier(CHECK_OK); - ParseFunctionLiteral(CHECK_OK); - return kUnknownStatement; -} + Identifier identifier = ParseIdentifier(CHECK_OK); + i::Scanner::Location location = scanner_->location(); -// Language extension which is only enabled for source files loaded -// through the API's extension mechanism. A native function -// declaration is resolved by looking up the function through a -// callback provided by the extension. -PreParser::Statement PreParser::ParseNativeDeclaration(bool* ok) { - Expect(i::Token::NATIVE, CHECK_OK); - Expect(i::Token::FUNCTION, CHECK_OK); - ParseIdentifier(CHECK_OK); - Expect(i::Token::LPAREN, CHECK_OK); - bool done = (peek() == i::Token::RPAREN); - while (!done) { - ParseIdentifier(CHECK_OK); - done = (peek() == i::Token::RPAREN); - if (!done) { - Expect(i::Token::COMMA, CHECK_OK); + Expression function_value = ParseFunctionLiteral(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()) { + type = "strict_reserved_word"; } + ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); + *ok = false; } - Expect(i::Token::RPAREN, CHECK_OK); - Expect(i::Token::SEMICOLON, CHECK_OK); - return kUnknownStatement; + return Statement::FunctionDeclaration(); } @@ -234,10 +257,18 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) { // Expect(i::Token::LBRACE, CHECK_OK); while (peek() != i::Token::RBRACE) { - ParseStatement(CHECK_OK); + i::Scanner::Location start_location = scanner_->peek_location(); + Statement statement = ParseStatement(CHECK_OK); + i::Scanner::Location end_location = scanner_->location(); + if (strict_mode() && statement.IsFunctionDeclaration()) { + ReportMessageAt(start_location.beg_pos, end_location.end_pos, + "strict_function", NULL); + *ok = false; + return Statement::Default(); + } } - Expect(i::Token::RBRACE, CHECK_OK); - return kUnknownStatement; + Expect(i::Token::RBRACE, ok); + return Statement::Default(); } @@ -265,10 +296,17 @@ PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN, if (peek() == i::Token::VAR) { Consume(i::Token::VAR); } else if (peek() == i::Token::CONST) { + if (strict_mode()) { + i::Scanner::Location location = scanner_->peek_location(); + ReportMessageAt(location.beg_pos, location.end_pos, + "strict_const", NULL); + *ok = false; + return Statement::Default(); + } Consume(i::Token::CONST); } else { *ok = false; - return 0; + return Statement::Default(); } // The scope of a variable/const declared anywhere inside a function @@ -277,7 +315,14 @@ PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN, do { // Parse variable name. if (nvars > 0) Consume(i::Token::COMMA); - ParseIdentifier(CHECK_OK); + Identifier identifier = ParseIdentifier(CHECK_OK); + if (strict_mode() && !identifier.IsValidStrictVariable()) { + StrictModeIdentifierViolation(scanner_->location(), + "strict_var_name", + identifier, + ok); + return Statement::Default(); + } nvars++; if (peek() == i::Token::ASSIGN) { Expect(i::Token::ASSIGN, CHECK_OK); @@ -286,24 +331,37 @@ PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN, } while (peek() == i::Token::COMMA); if (num_decl != NULL) *num_decl = nvars; - return kUnknownStatement; + return Statement::Default(); } -PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( - bool* ok) { +PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { // ExpressionStatement | LabelledStatement :: // Expression ';' // Identifier ':' Statement Expression expr = ParseExpression(true, CHECK_OK); - if (peek() == i::Token::COLON && expr == kIdentifierExpression) { - Consume(i::Token::COLON); - return ParseStatement(ok); + if (expr.IsRawIdentifier()) { + if (peek() == i::Token::COLON && + (!strict_mode() || !expr.AsIdentifier().IsFutureReserved())) { + Consume(i::Token::COLON); + i::Scanner::Location start_location = scanner_->peek_location(); + Statement statement = ParseStatement(CHECK_OK); + if (strict_mode() && statement.IsFunctionDeclaration()) { + i::Scanner::Location end_location = scanner_->location(); + ReportMessageAt(start_location.beg_pos, end_location.end_pos, + "strict_function", NULL); + *ok = false; + } + return Statement::Default(); + } + // 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. } // Parsed expression statement. ExpectSemicolon(CHECK_OK); - return kUnknownStatement; + return Statement::ExpressionStatement(expr); } @@ -320,7 +378,7 @@ PreParser::Statement PreParser::ParseIfStatement(bool* ok) { Next(); ParseStatement(CHECK_OK); } - return kUnknownStatement; + return Statement::Default(); } @@ -330,14 +388,14 @@ PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { Expect(i::Token::CONTINUE, CHECK_OK); i::Token::Value tok = peek(); - if (!scanner_->has_line_terminator_before_next() && + if (!scanner_->HasAnyLineTerminatorBeforeNext() && tok != i::Token::SEMICOLON && tok != i::Token::RBRACE && tok != i::Token::EOS) { ParseIdentifier(CHECK_OK); } ExpectSemicolon(CHECK_OK); - return kUnknownStatement; + return Statement::Default(); } @@ -347,14 +405,14 @@ PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { Expect(i::Token::BREAK, CHECK_OK); i::Token::Value tok = peek(); - if (!scanner_->has_line_terminator_before_next() && + if (!scanner_->HasAnyLineTerminatorBeforeNext() && tok != i::Token::SEMICOLON && tok != i::Token::RBRACE && tok != i::Token::EOS) { ParseIdentifier(CHECK_OK); } ExpectSemicolon(CHECK_OK); - return kUnknownStatement; + return Statement::Default(); } @@ -373,14 +431,14 @@ PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { // This is not handled during preparsing. i::Token::Value tok = peek(); - if (!scanner_->has_line_terminator_before_next() && + if (!scanner_->HasAnyLineTerminatorBeforeNext() && tok != i::Token::SEMICOLON && tok != i::Token::RBRACE && tok != i::Token::EOS) { ParseExpression(true, CHECK_OK); } ExpectSemicolon(CHECK_OK); - return kUnknownStatement; + return Statement::Default(); } @@ -388,6 +446,13 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) { // WithStatement :: // 'with' '(' Expression ')' Statement Expect(i::Token::WITH, CHECK_OK); + if (strict_mode()) { + i::Scanner::Location location = scanner_->location(); + ReportMessageAt(location.beg_pos, location.end_pos, + "strict_mode_with", NULL); + *ok = false; + return Statement::Default(); + } Expect(i::Token::LPAREN, CHECK_OK); ParseExpression(true, CHECK_OK); Expect(i::Token::RPAREN, CHECK_OK); @@ -395,7 +460,7 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) { scope_->EnterWith(); ParseStatement(CHECK_OK); scope_->LeaveWith(); - return kUnknownStatement; + return Statement::Default(); } @@ -419,13 +484,20 @@ PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { Expect(i::Token::DEFAULT, CHECK_OK); Expect(i::Token::COLON, CHECK_OK); } else { - ParseStatement(CHECK_OK); + i::Scanner::Location start_location = scanner_->peek_location(); + Statement statement = ParseStatement(CHECK_OK); + if (strict_mode() && statement.IsFunctionDeclaration()) { + i::Scanner::Location end_location = scanner_->location(); + ReportMessageAt(start_location.beg_pos, end_location.end_pos, + "strict_function", NULL); + *ok = false; + return Statement::Default(); + } } token = peek(); } - Expect(i::Token::RBRACE, CHECK_OK); - - return kUnknownStatement; + Expect(i::Token::RBRACE, ok); + return Statement::Default(); } @@ -438,8 +510,8 @@ PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { Expect(i::Token::WHILE, CHECK_OK); Expect(i::Token::LPAREN, CHECK_OK); ParseExpression(true, CHECK_OK); - Expect(i::Token::RPAREN, CHECK_OK); - return kUnknownStatement; + Expect(i::Token::RPAREN, ok); + return Statement::Default(); } @@ -451,8 +523,8 @@ PreParser::Statement PreParser::ParseWhileStatement(bool* ok) { Expect(i::Token::LPAREN, CHECK_OK); ParseExpression(true, CHECK_OK); Expect(i::Token::RPAREN, CHECK_OK); - ParseStatement(CHECK_OK); - return kUnknownStatement; + ParseStatement(ok); + return Statement::Default(); } @@ -472,7 +544,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) { Expect(i::Token::RPAREN, CHECK_OK); ParseStatement(CHECK_OK); - return kUnknownStatement; + return Statement::Default(); } } else { ParseExpression(false, CHECK_OK); @@ -482,7 +554,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) { Expect(i::Token::RPAREN, CHECK_OK); ParseStatement(CHECK_OK); - return kUnknownStatement; + return Statement::Default(); } } } @@ -500,8 +572,8 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) { } Expect(i::Token::RPAREN, CHECK_OK); - ParseStatement(CHECK_OK); - return kUnknownStatement; + ParseStatement(ok); + return Statement::Default(); } @@ -510,17 +582,16 @@ PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { // 'throw' [no line terminator] Expression ';' Expect(i::Token::THROW, CHECK_OK); - if (scanner_->has_line_terminator_before_next()) { + if (scanner_->HasAnyLineTerminatorBeforeNext()) { i::JavaScriptScanner::Location pos = scanner_->location(); ReportMessageAt(pos.beg_pos, pos.end_pos, "newline_after_throw", NULL); *ok = false; - return kUnknownStatement; + return Statement::Default(); } ParseExpression(true, CHECK_OK); - ExpectSemicolon(CHECK_OK); - - return kUnknownStatement; + ExpectSemicolon(ok); + return Statement::Default(); } @@ -547,12 +618,19 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) { if (peek() == i::Token::CATCH) { Consume(i::Token::CATCH); Expect(i::Token::LPAREN, CHECK_OK); - ParseIdentifier(CHECK_OK); + Identifier id = ParseIdentifier(CHECK_OK); + if (strict_mode() && !id.IsValidStrictVariable()) { + StrictModeIdentifierViolation(scanner_->location(), + "strict_catch_variable", + id, + ok); + return Statement::Default(); + } Expect(i::Token::RPAREN, CHECK_OK); scope_->EnterWith(); ParseBlock(ok); scope_->LeaveWith(); - if (!*ok) return kUnknownStatement; + if (!*ok) Statement::Default(); catch_or_finally_seen = true; } if (peek() == i::Token::FINALLY) { @@ -563,7 +641,7 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) { if (!catch_or_finally_seen) { *ok = false; } - return kUnknownStatement; + return Statement::Default(); } @@ -575,11 +653,19 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { // 'debugger' ';' Expect(i::Token::DEBUGGER, CHECK_OK); - ExpectSemicolon(CHECK_OK); - return kUnknownStatement; + ExpectSemicolon(ok); + return Statement::Default(); } +#undef CHECK_OK +#define CHECK_OK ok); \ + if (!*ok) return Expression::Default(); \ + ((void)0 +#define DUMMY ) // to make indentation work +#undef DUMMY + + // Precedence = 1 PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) { // Expression :: @@ -590,7 +676,7 @@ PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) { while (peek() == i::Token::COMMA) { Expect(i::Token::COMMA, CHECK_OK); ParseAssignmentExpression(accept_IN, CHECK_OK); - result = kUnknownExpression; + result = Expression::Default(); } return result; } @@ -603,6 +689,7 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN, // ConditionalExpression // LeftHandSideExpression AssignmentOperator AssignmentExpression + i::Scanner::Location before = scanner_->peek_location(); Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); if (!i::Token::IsAssignmentOp(peek())) { @@ -610,14 +697,23 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN, return expression; } + if (strict_mode() && expression.IsIdentifier() && + expression.AsIdentifier().IsEvalOrArguments()) { + i::Scanner::Location after = scanner_->location(); + ReportMessageAt(before.beg_pos, after.end_pos, + "strict_lhs_assignment", NULL); + *ok = false; + return Expression::Default(); + } + i::Token::Value op = Next(); // Get assignment operator. ParseAssignmentExpression(accept_IN, CHECK_OK); - if ((op == i::Token::ASSIGN) && (expression == kThisPropertyExpression)) { + if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) { scope_->AddProperty(); } - return kUnknownExpression; + return Expression::Default(); } @@ -638,7 +734,7 @@ PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN, ParseAssignmentExpression(true, CHECK_OK); Expect(i::Token::COLON, CHECK_OK); ParseAssignmentExpression(accept_IN, CHECK_OK); - return kUnknownExpression; + return Expression::Default(); } @@ -660,7 +756,7 @@ PreParser::Expression PreParser::ParseBinaryExpression(int prec, while (Precedence(peek(), accept_IN) == prec1) { Next(); ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK); - result = kUnknownExpression; + result = Expression::Default(); } } return result; @@ -681,10 +777,22 @@ PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) { // '!' UnaryExpression i::Token::Value op = peek(); - if (i::Token::IsUnaryOp(op) || i::Token::IsCountOp(op)) { + if (i::Token::IsUnaryOp(op)) { op = Next(); ParseUnaryExpression(ok); - return kUnknownExpression; + return Expression::Default(); + } else if (i::Token::IsCountOp(op)) { + op = Next(); + i::Scanner::Location before = scanner_->peek_location(); + Expression expression = ParseUnaryExpression(CHECK_OK); + if (strict_mode() && expression.IsIdentifier() && + expression.AsIdentifier().IsEvalOrArguments()) { + i::Scanner::Location after = scanner_->location(); + ReportMessageAt(before.beg_pos, after.end_pos, + "strict_lhs_prefix", NULL); + *ok = false; + } + return Expression::Default(); } else { return ParsePostfixExpression(ok); } @@ -695,11 +803,20 @@ PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) { // PostfixExpression :: // LeftHandSideExpression ('++' | '--')? + i::Scanner::Location before = scanner_->peek_location(); Expression expression = ParseLeftHandSideExpression(CHECK_OK); - if (!scanner_->has_line_terminator_before_next() && + if (!scanner_->HasAnyLineTerminatorBeforeNext() && i::Token::IsCountOp(peek())) { + if (strict_mode() && expression.IsIdentifier() && + expression.AsIdentifier().IsEvalOrArguments()) { + i::Scanner::Location after = scanner_->location(); + ReportMessageAt(before.beg_pos, after.end_pos, + "strict_lhs_postfix", NULL); + *ok = false; + return Expression::Default(); + } Next(); - return kUnknownExpression; + return Expression::Default(); } return expression; } @@ -709,7 +826,7 @@ PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) { // LeftHandSideExpression :: // (NewExpression | MemberExpression) ... - Expression result; + Expression result = Expression::Default(); if (peek() == i::Token::NEW) { result = ParseNewExpression(CHECK_OK); } else { @@ -722,27 +839,27 @@ PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) { Consume(i::Token::LBRACK); ParseExpression(true, CHECK_OK); Expect(i::Token::RBRACK, CHECK_OK); - if (result == kThisExpression) { - result = kThisPropertyExpression; + if (result.IsThis()) { + result = Expression::ThisProperty(); } else { - result = kUnknownExpression; + result = Expression::Default(); } break; } case i::Token::LPAREN: { ParseArguments(CHECK_OK); - result = kUnknownExpression; + result = Expression::Default(); break; } case i::Token::PERIOD: { Consume(i::Token::PERIOD); ParseIdentifierName(CHECK_OK); - if (result == kThisExpression) { - result = kThisPropertyExpression; + if (result.IsThis()) { + result = Expression::ThisProperty(); } else { - result = kUnknownExpression; + result = Expression::Default(); } break; } @@ -788,13 +905,21 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( // ('[' Expression ']' | '.' Identifier | Arguments)* // Parse the initial primary or function expression. - Expression result = kUnknownExpression; + Expression result = Expression::Default(); if (peek() == i::Token::FUNCTION) { Consume(i::Token::FUNCTION); + Identifier identifier = Identifier::Default(); if (peek_any_identifier()) { - ParseIdentifier(CHECK_OK); + identifier = ParseIdentifier(CHECK_OK); } result = ParseFunctionLiteral(CHECK_OK); + if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) { + StrictModeIdentifierViolation(scanner_->location(), + "strict_function_name", + identifier, + ok); + return Expression::Default(); + } } else { result = ParsePrimaryExpression(CHECK_OK); } @@ -805,20 +930,20 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( Consume(i::Token::LBRACK); ParseExpression(true, CHECK_OK); Expect(i::Token::RBRACK, CHECK_OK); - if (result == kThisExpression) { - result = kThisPropertyExpression; + if (result.IsThis()) { + result = Expression::ThisProperty(); } else { - result = kUnknownExpression; + result = Expression::Default(); } break; } case i::Token::PERIOD: { Consume(i::Token::PERIOD); ParseIdentifierName(CHECK_OK); - if (result == kThisExpression) { - result = kThisPropertyExpression; + if (result.IsThis()) { + result = Expression::ThisProperty(); } else { - result = kUnknownExpression; + result = Expression::Default(); } break; } @@ -827,7 +952,7 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( // Consume one of the new prefixes (already parsed). ParseArguments(CHECK_OK); new_count--; - result = kUnknownExpression; + result = Expression::Default(); break; } default: @@ -851,18 +976,36 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { // RegExpLiteral // '(' Expression ')' - Expression result = kUnknownExpression; + Expression result = Expression::Default(); switch (peek()) { case i::Token::THIS: { Next(); - result = kThisExpression; + result = Expression::This(); break; } - case i::Token::IDENTIFIER: case i::Token::FUTURE_RESERVED_WORD: { - ParseIdentifier(CHECK_OK); - result = kIdentifierExpression; + Next(); + i::Scanner::Location location = scanner_->location(); + ReportMessageAt(location.beg_pos, location.end_pos, + "reserved_word", NULL); + *ok = false; + return Expression::Default(); + } + + case i::Token::FUTURE_STRICT_RESERVED_WORD: + if (strict_mode()) { + Next(); + i::Scanner::Location location = scanner_->location(); + ReportMessageAt(location.beg_pos, location.end_pos, + "strict_reserved_word", NULL); + *ok = false; + return Expression::Default(); + } + // FALLTHROUGH + case i::Token::IDENTIFIER: { + Identifier id = ParseIdentifier(CHECK_OK); + result = Expression::FromIdentifier(id); break; } @@ -900,7 +1043,7 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { parenthesized_function_ = (peek() == i::Token::FUNCTION); result = ParseExpression(true, CHECK_OK); Expect(i::Token::RPAREN, CHECK_OK); - if (result == kIdentifierExpression) result = kUnknownExpression; + result = result.Parenthesize(); break; case i::Token::MOD: @@ -910,7 +1053,7 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { default: { Next(); *ok = false; - return kUnknownExpression; + return Expression::Default(); } } @@ -933,7 +1076,7 @@ PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) { Expect(i::Token::RBRACK, CHECK_OK); scope_->NextMaterializedLiteralIndex(); - return kUnknownExpression; + return Expression::Default(); } @@ -949,20 +1092,22 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { i::Token::Value next = peek(); switch (next) { case i::Token::IDENTIFIER: - case i::Token::FUTURE_RESERVED_WORD: { + case i::Token::FUTURE_RESERVED_WORD: + case i::Token::FUTURE_STRICT_RESERVED_WORD: { bool is_getter = false; bool is_setter = false; - ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); + ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); if ((is_getter || is_setter) && peek() != i::Token::COLON) { i::Token::Value name = Next(); bool is_keyword = i::Token::IsKeyword(name); if (name != i::Token::IDENTIFIER && name != i::Token::FUTURE_RESERVED_WORD && + name != i::Token::FUTURE_STRICT_RESERVED_WORD && name != i::Token::NUMBER && name != i::Token::STRING && !is_keyword) { *ok = false; - return kUnknownExpression; + return Expression::Default(); } if (!is_keyword) { LogSymbol(); @@ -988,7 +1133,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { } else { // Unexpected token. *ok = false; - return kUnknownExpression; + return Expression::Default(); } } @@ -1001,7 +1146,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { Expect(i::Token::RBRACE, CHECK_OK); scope_->NextMaterializedLiteralIndex(); - return kUnknownExpression; + return Expression::Default(); } @@ -1013,7 +1158,7 @@ PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal, ReportMessageAt(location.beg_pos, location.end_pos, "unterminated_regexp", NULL); *ok = false; - return kUnknownExpression; + return Expression::Default(); } scope_->NextMaterializedLiteralIndex(); @@ -1024,10 +1169,10 @@ PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal, ReportMessageAt(location.beg_pos, location.end_pos, "invalid_regexp_flags", NULL); *ok = false; - return kUnknownExpression; + return Expression::Default(); } Next(); - return kUnknownExpression; + return Expression::Default(); } @@ -1035,16 +1180,21 @@ PreParser::Arguments PreParser::ParseArguments(bool* ok) { // Arguments :: // '(' (AssignmentExpression)*[','] ')' - Expect(i::Token::LPAREN, CHECK_OK); + Expect(i::Token::LPAREN, ok); + if (!*ok) return -1; bool done = (peek() == i::Token::RPAREN); int argc = 0; while (!done) { - ParseAssignmentExpression(true, CHECK_OK); + ParseAssignmentExpression(true, ok); + if (!*ok) return -1; argc++; done = (peek() == i::Token::RPAREN); - if (!done) Expect(i::Token::COMMA, CHECK_OK); + if (!done) { + Expect(i::Token::COMMA, ok); + if (!*ok) return -1; + } } - Expect(i::Token::RPAREN, CHECK_OK); + Expect(i::Token::RPAREN, ok); return argc; } @@ -1057,13 +1207,19 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) { ScopeType outer_scope_type = scope_->type(); bool inside_with = scope_->IsInsideWith(); Scope function_scope(&scope_, kFunctionScope); - // FormalParameterList :: // '(' (Identifier)*[','] ')' Expect(i::Token::LPAREN, CHECK_OK); + int start_position = scanner_->location().beg_pos; bool done = (peek() == i::Token::RPAREN); while (!done) { - ParseIdentifier(CHECK_OK); + Identifier id = ParseIdentifier(CHECK_OK); + if (!id.IsValidStrictVariable()) { + StrictModeIdentifierViolation(scanner_->location(), + "strict_param_name", + id, + CHECK_OK); + } done = (peek() == i::Token::RPAREN); if (!done) { Expect(i::Token::COMMA, CHECK_OK); @@ -1086,7 +1242,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) { log_->PauseRecording(); ParseSourceElements(i::Token::RBRACE, ok); log_->ResumeRecording(); - if (!*ok) return kUnknownExpression; + if (!*ok) Expression::Default(); Expect(i::Token::RBRACE, CHECK_OK); @@ -1094,12 +1250,21 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) { int end_pos = scanner_->location().end_pos; log_->LogFunction(function_block_pos, end_pos, function_scope.materialized_literal_count(), - function_scope.expected_properties()); + function_scope.expected_properties(), + strict_mode() ? 1 : 0); } else { ParseSourceElements(i::Token::RBRACE, CHECK_OK); Expect(i::Token::RBRACE, CHECK_OK); } - return kUnknownExpression; + + if (strict_mode()) { + int end_position = scanner_->location().end_pos; + CheckOctalLiteral(start_position, end_position, CHECK_OK); + CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK); + return Expression::StrictFunction(); + } + + return Expression::Default(); } @@ -1109,11 +1274,13 @@ PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { Expect(i::Token::MOD, CHECK_OK); ParseIdentifier(CHECK_OK); - ParseArguments(CHECK_OK); + ParseArguments(ok); - return kUnknownExpression; + return Expression::Default(); } +#undef CHECK_OK + void PreParser::ExpectSemicolon(bool* ok) { // Check for automatic semicolon insertion according to @@ -1123,7 +1290,7 @@ void PreParser::ExpectSemicolon(bool* ok) { Next(); return; } - if (scanner_->has_line_terminator_before_next() || + if (scanner_->HasAnyLineTerminatorBeforeNext() || tok == i::Token::RBRACE || tok == i::Token::EOS) { return; @@ -1142,24 +1309,111 @@ void PreParser::LogSymbol() { } -PreParser::Identifier PreParser::GetIdentifierSymbol() { +PreParser::Expression PreParser::GetStringSymbol() { + const int kUseStrictLength = 10; + const char* kUseStrictChars = "use strict"; LogSymbol(); - return kUnknownIdentifier; + 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::Expression PreParser::GetStringSymbol() { +PreParser::Identifier PreParser::GetIdentifierSymbol() { LogSymbol(); - return kUnknownExpression; + if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) { + return Identifier::FutureReserved(); + } else if (scanner_->current_token() == + i::Token::FUTURE_STRICT_RESERVED_WORD) { + return Identifier::FutureStrictReserved(); + } + 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) { - if (!Check(i::Token::FUTURE_RESERVED_WORD)) { - Expect(i::Token::IDENTIFIER, ok); + i::Token::Value next = Next(); + switch (next) { + case i::Token::FUTURE_RESERVED_WORD: { + i::Scanner::Location location = scanner_->location(); + ReportMessageAt(location.beg_pos, location.end_pos, + "reserved_word", NULL); + *ok = false; + } + // FALLTHROUGH + case i::Token::FUTURE_STRICT_RESERVED_WORD: + case i::Token::IDENTIFIER: + return GetIdentifierSymbol(); + default: + *ok = false; + return Identifier::Default(); + } +} + + +void PreParser::SetStrictModeViolation(i::Scanner::Location location, + const char* type, + bool* ok) { + if (strict_mode()) { + ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); + *ok = false; + return; } - if (!*ok) return kUnknownIdentifier; - return GetIdentifierSymbol(); + // 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). + strict_mode_violation_location_ = location; + strict_mode_violation_type_ = type; +} + + +void PreParser::CheckDelayedStrictModeViolation(int beg_pos, + int end_pos, + bool* ok) { + i::Scanner::Location location = strict_mode_violation_location_; + if (location.IsValid() && + location.beg_pos > beg_pos && location.end_pos < end_pos) { + ReportMessageAt(location.beg_pos, location.end_pos, + strict_mode_violation_type_, NULL); + *ok = false; + } + strict_mode_violation_location_ = i::Scanner::Location::invalid(); +} + + +void PreParser::StrictModeIdentifierViolation(i::Scanner::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()) { + type = "strict_reserved_word"; + } + if (strict_mode()) { + ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); + *ok = false; + return; + } + strict_mode_violation_location_ = location; + strict_mode_violation_type_ = type; } @@ -1170,24 +1424,29 @@ PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { const char* keyword = i::Token::String(next); log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword, i::StrLength(keyword))); - return kUnknownExpression; + return Identifier::Default(); } if (next == i::Token::IDENTIFIER || - next == i::Token::FUTURE_RESERVED_WORD) { + next == i::Token::FUTURE_RESERVED_WORD || + next == i::Token::FUTURE_STRICT_RESERVED_WORD) { return GetIdentifierSymbol(); } *ok = false; - return kUnknownIdentifier; + return Identifier::Default(); } +#undef CHECK_OK + // This function reads an identifier and determines whether or not it // is 'get' or 'set'. -PreParser::Identifier PreParser::ParseIdentifierOrGetOrSet(bool* is_get, - bool* is_set, - bool* ok) { - PreParser::Identifier result = ParseIdentifier(CHECK_OK); - if (scanner_->is_literal_ascii() && scanner_->literal_length() == 3) { +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; @@ -1198,8 +1457,7 @@ PreParser::Identifier PreParser::ParseIdentifierOrGetOrSet(bool* is_get, bool PreParser::peek_any_identifier() { i::Token::Value next = peek(); return next == i::Token::IDENTIFIER || - next == i::Token::FUTURE_RESERVED_WORD; + next == i::Token::FUTURE_RESERVED_WORD || + next == i::Token::FUTURE_STRICT_RESERVED_WORD; } - -#undef CHECK_OK } } // v8::preparser |