diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-06-06 10:28:14 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-06-07 10:33:31 +0200 |
commit | 3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09 (patch) | |
tree | 9dee56e142638b34f1eccbd0ad88c3bce5377c29 /deps/v8/src/parsing/scanner.cc | |
parent | 91a1bbe3055a660194ca4d403795aa0c03e9d056 (diff) | |
download | node-new-3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09.tar.gz |
deps: update V8 to 5.9.211.32
PR-URL: https://github.com/nodejs/node/pull/13263
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Diffstat (limited to 'deps/v8/src/parsing/scanner.cc')
-rw-r--r-- | deps/v8/src/parsing/scanner.cc | 191 |
1 files changed, 132 insertions, 59 deletions
diff --git a/deps/v8/src/parsing/scanner.cc b/deps/v8/src/parsing/scanner.cc index c1580bbeae..81839990c6 100644 --- a/deps/v8/src/parsing/scanner.cc +++ b/deps/v8/src/parsing/scanner.cc @@ -19,10 +19,7 @@ namespace v8 { namespace internal { -// Scoped helper for saving & restoring scanner error state. -// This is used for tagged template literals, in which normally forbidden -// escape sequences are allowed. -class ErrorState { +class Scanner::ErrorState { public: ErrorState(MessageTemplate::Template* message_stack, Scanner::Location* location_stack) @@ -31,7 +28,7 @@ class ErrorState { location_stack_(location_stack), old_location_(*location_stack) { *message_stack_ = MessageTemplate::kNone; - *location_stack_ = Scanner::Location::invalid(); + *location_stack_ = Location::invalid(); } ~ErrorState() { @@ -39,17 +36,16 @@ class ErrorState { *location_stack_ = old_location_; } - void MoveErrorTo(MessageTemplate::Template* message_dest, - Scanner::Location* location_dest) { + void MoveErrorTo(TokenDesc* dest) { if (*message_stack_ == MessageTemplate::kNone) { return; } - if (*message_dest == MessageTemplate::kNone) { - *message_dest = *message_stack_; - *location_dest = *location_stack_; + if (dest->invalid_template_escape_message == MessageTemplate::kNone) { + dest->invalid_template_escape_message = *message_stack_; + dest->invalid_template_escape_location = *location_stack_; } *message_stack_ = MessageTemplate::kNone; - *location_stack_ = Scanner::Location::invalid(); + *location_stack_ = Location::invalid(); } private: @@ -59,6 +55,9 @@ class ErrorState { Scanner::Location const old_location_; }; +// ---------------------------------------------------------------------------- +// Scanner::LiteralBuffer + Handle<String> Scanner::LiteralBuffer::Internalize(Isolate* isolate) const { if (is_one_byte()) { return isolate->factory()->InternalizeOneByteString(one_byte_literal()); @@ -184,6 +183,7 @@ Scanner::Scanner(UnicodeCache* unicode_cache) found_html_comment_(false) {} void Scanner::Initialize(Utf16CharacterStream* source) { + DCHECK_NOT_NULL(source); source_ = source; // Need to capture identifiers in order to recognize "get" and "set" // in object literals. @@ -383,6 +383,7 @@ Token::Value Scanner::Next() { if (V8_UNLIKELY(next_next_.token != Token::UNINITIALIZED)) { next_ = next_next_; next_next_.token = Token::UNINITIALIZED; + next_next_.contextual_token = Token::UNINITIALIZED; has_line_terminator_before_next_ = has_line_terminator_after_next_; return current_.token; } @@ -393,10 +394,12 @@ Token::Value Scanner::Next() { if (token != Token::ILLEGAL) { int pos = source_pos(); next_.token = token; + next_.contextual_token = Token::UNINITIALIZED; next_.location.beg_pos = pos; next_.location.end_pos = pos + 1; next_.literal_chars = nullptr; next_.raw_literal_chars = nullptr; + next_.invalid_template_escape_message = MessageTemplate::kNone; Advance(); return current_.token; } @@ -609,6 +612,7 @@ Token::Value Scanner::ScanHtmlComment() { void Scanner::Scan() { next_.literal_chars = NULL; next_.raw_literal_chars = NULL; + next_.invalid_template_escape_message = MessageTemplate::kNone; Token::Value token; do { // Remember the position of the next token @@ -627,7 +631,8 @@ void Scanner::Scan() { token = Token::WHITESPACE; break; - case '"': case '\'': + case '"': + case '\'': token = ScanString(); break; @@ -872,7 +877,13 @@ void Scanner::Scan() { } while (token == Token::WHITESPACE); next_.location.end_pos = source_pos(); - next_.token = token; + if (Token::IsContextualKeyword(token)) { + next_.token = Token::IDENTIFIER; + next_.contextual_token = token; + } else { + next_.token = token; + next_.contextual_token = Token::UNINITIALIZED; + } #ifdef DEBUG SanityCheckTokenDesc(current_); @@ -889,6 +900,8 @@ void Scanner::SanityCheckTokenDesc(const TokenDesc& token) const { // - TEMPLATE_*: need both literal + raw literal chars. // - IDENTIFIERS, STRINGS, etc.: need a literal, but no raw literal. // - all others: should have neither. + // Furthermore, only TEMPLATE_* tokens can have a + // invalid_template_escape_message. switch (token.token) { case Token::UNINITIALIZED: @@ -909,12 +922,21 @@ void Scanner::SanityCheckTokenDesc(const TokenDesc& token) const { case Token::STRING: DCHECK_NOT_NULL(token.literal_chars); DCHECK_NULL(token.raw_literal_chars); + DCHECK_EQ(token.invalid_template_escape_message, MessageTemplate::kNone); break; default: DCHECK_NULL(token.literal_chars); DCHECK_NULL(token.raw_literal_chars); + DCHECK_EQ(token.invalid_template_escape_message, MessageTemplate::kNone); break; } + + DCHECK_IMPLIES(token.token != Token::IDENTIFIER, + token.contextual_token == Token::UNINITIALIZED); + DCHECK_IMPLIES(token.contextual_token != Token::UNINITIALIZED, + token.token == Token::IDENTIFIER && + Token::IsContextualKeyword(token.contextual_token)); + DCHECK(!Token::IsContextualKeyword(token.token)); } #endif // DEBUG @@ -1117,10 +1139,8 @@ Token::Value Scanner::ScanTemplateSpan() { DCHECK_EQ(!success, has_error()); // For templates, invalid escape sequence checking is handled in the // parser. - scanner_error_state.MoveErrorTo(&invalid_template_escape_message_, - &invalid_template_escape_location_); - octal_error_state.MoveErrorTo(&invalid_template_escape_message_, - &invalid_template_escape_location_); + scanner_error_state.MoveErrorTo(&next_); + octal_error_state.MoveErrorTo(&next_); } } else if (c < 0) { // Unterminated template literal @@ -1145,6 +1165,7 @@ Token::Value Scanner::ScanTemplateSpan() { literal.Complete(); next_.location.end_pos = source_pos(); next_.token = result; + next_.contextual_token = Token::UNINITIALIZED; return result; } @@ -1165,6 +1186,18 @@ Token::Value Scanner::ScanTemplateContinuation() { return ScanTemplateSpan(); } +Handle<String> Scanner::SourceUrl(Isolate* isolate) const { + Handle<String> tmp; + if (source_url_.length() > 0) tmp = source_url_.Internalize(isolate); + return tmp; +} + +Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const { + Handle<String> tmp; + if (source_mapping_url_.length() > 0) + tmp = source_mapping_url_.Internalize(isolate); + return tmp; +} void Scanner::ScanDecimalDigits() { while (IsDecimalDigit(c0_)) @@ -1356,8 +1389,11 @@ uc32 Scanner::ScanUnicodeEscape() { #define KEYWORDS(KEYWORD_GROUP, KEYWORD) \ KEYWORD_GROUP('a') \ + KEYWORD("arguments", Token::ARGUMENTS) \ + KEYWORD("as", Token::AS) \ KEYWORD("async", Token::ASYNC) \ KEYWORD("await", Token::AWAIT) \ + KEYWORD("anonymous", Token::ANONYMOUS) \ KEYWORD_GROUP('b') \ KEYWORD("break", Token::BREAK) \ KEYWORD_GROUP('c') \ @@ -1365,6 +1401,7 @@ uc32 Scanner::ScanUnicodeEscape() { KEYWORD("catch", Token::CATCH) \ KEYWORD("class", Token::CLASS) \ KEYWORD("const", Token::CONST) \ + KEYWORD("constructor", Token::CONSTRUCTOR) \ KEYWORD("continue", Token::CONTINUE) \ KEYWORD_GROUP('d') \ KEYWORD("debugger", Token::DEBUGGER) \ @@ -1374,13 +1411,17 @@ uc32 Scanner::ScanUnicodeEscape() { KEYWORD_GROUP('e') \ KEYWORD("else", Token::ELSE) \ KEYWORD("enum", Token::ENUM) \ + KEYWORD("eval", Token::EVAL) \ KEYWORD("export", Token::EXPORT) \ KEYWORD("extends", Token::EXTENDS) \ KEYWORD_GROUP('f') \ KEYWORD("false", Token::FALSE_LITERAL) \ KEYWORD("finally", Token::FINALLY) \ KEYWORD("for", Token::FOR) \ + KEYWORD("from", Token::FROM) \ KEYWORD("function", Token::FUNCTION) \ + KEYWORD_GROUP('g') \ + KEYWORD("get", Token::GET) \ KEYWORD_GROUP('i') \ KEYWORD("if", Token::IF) \ KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \ @@ -1391,25 +1432,34 @@ uc32 Scanner::ScanUnicodeEscape() { KEYWORD_GROUP('l') \ KEYWORD("let", Token::LET) \ KEYWORD_GROUP('n') \ + KEYWORD("name", Token::NAME) \ KEYWORD("new", Token::NEW) \ KEYWORD("null", Token::NULL_LITERAL) \ + KEYWORD_GROUP('o') \ + KEYWORD("of", Token::OF) \ KEYWORD_GROUP('p') \ KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD) \ KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD) \ KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD) \ + KEYWORD("prototype", Token::PROTOTYPE) \ KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD) \ KEYWORD_GROUP('r') \ KEYWORD("return", Token::RETURN) \ KEYWORD_GROUP('s') \ + KEYWORD("sent", Token::SENT) \ + KEYWORD("set", Token::SET) \ KEYWORD("static", Token::STATIC) \ KEYWORD("super", Token::SUPER) \ KEYWORD("switch", Token::SWITCH) \ KEYWORD_GROUP('t') \ + KEYWORD("target", Token::TARGET) \ KEYWORD("this", Token::THIS) \ KEYWORD("throw", Token::THROW) \ KEYWORD("true", Token::TRUE_LITERAL) \ KEYWORD("try", Token::TRY) \ KEYWORD("typeof", Token::TYPEOF) \ + KEYWORD_GROUP('u') \ + KEYWORD("undefined", Token::UNDEFINED) \ KEYWORD_GROUP('v') \ KEYWORD("var", Token::VAR) \ KEYWORD("void", Token::VOID) \ @@ -1417,13 +1467,15 @@ uc32 Scanner::ScanUnicodeEscape() { KEYWORD("while", Token::WHILE) \ KEYWORD("with", Token::WITH) \ KEYWORD_GROUP('y') \ - KEYWORD("yield", Token::YIELD) + KEYWORD("yield", Token::YIELD) \ + KEYWORD_GROUP('_') \ + KEYWORD("__proto__", Token::PROTO_UNDERSCORED) static Token::Value KeywordOrIdentifierToken(const uint8_t* input, int input_length) { DCHECK(input_length >= 1); const int kMinLength = 2; - const int kMaxLength = 10; + const int kMaxLength = 11; if (input_length < kMinLength || input_length > kMaxLength) { return Token::IDENTIFIER; } @@ -1432,26 +1484,30 @@ static Token::Value KeywordOrIdentifierToken(const uint8_t* input, #define KEYWORD_GROUP_CASE(ch) \ break; \ case ch: -#define KEYWORD(keyword, token) \ - { \ - /* 'keyword' is a char array, so sizeof(keyword) is */ \ - /* strlen(keyword) plus 1 for the NUL char. */ \ - const int keyword_length = sizeof(keyword) - 1; \ - STATIC_ASSERT(keyword_length >= kMinLength); \ - STATIC_ASSERT(keyword_length <= kMaxLength); \ - if (input_length == keyword_length && input[1] == keyword[1] && \ - (keyword_length <= 2 || input[2] == keyword[2]) && \ - (keyword_length <= 3 || input[3] == keyword[3]) && \ - (keyword_length <= 4 || input[4] == keyword[4]) && \ - (keyword_length <= 5 || input[5] == keyword[5]) && \ - (keyword_length <= 6 || input[6] == keyword[6]) && \ - (keyword_length <= 7 || input[7] == keyword[7]) && \ - (keyword_length <= 8 || input[8] == keyword[8]) && \ - (keyword_length <= 9 || input[9] == keyword[9])) { \ - return token; \ - } \ +#define KEYWORD(keyword, token) \ + { \ + /* 'keyword' is a char array, so sizeof(keyword) is */ \ + /* strlen(keyword) plus 1 for the NUL char. */ \ + const int keyword_length = sizeof(keyword) - 1; \ + STATIC_ASSERT(keyword_length >= kMinLength); \ + STATIC_ASSERT(keyword_length <= kMaxLength); \ + DCHECK_EQ(input[0], keyword[0]); \ + DCHECK(token == Token::FUTURE_STRICT_RESERVED_WORD || \ + 0 == strncmp(keyword, Token::String(token), sizeof(keyword))); \ + if (input_length == keyword_length && input[1] == keyword[1] && \ + (keyword_length <= 2 || input[2] == keyword[2]) && \ + (keyword_length <= 3 || input[3] == keyword[3]) && \ + (keyword_length <= 4 || input[4] == keyword[4]) && \ + (keyword_length <= 5 || input[5] == keyword[5]) && \ + (keyword_length <= 6 || input[6] == keyword[6]) && \ + (keyword_length <= 7 || input[7] == keyword[7]) && \ + (keyword_length <= 8 || input[8] == keyword[8]) && \ + (keyword_length <= 9 || input[9] == keyword[9]) && \ + (keyword_length <= 10 || input[10] == keyword[10])) { \ + return token; \ + } \ } - KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD) + KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD) } return Token::IDENTIFIER; } @@ -1460,12 +1516,12 @@ static Token::Value KeywordOrIdentifierToken(const uint8_t* input, Token::Value Scanner::ScanIdentifierOrKeyword() { DCHECK(unicode_cache_->IsIdentifierStart(c0_)); LiteralScope literal(this); - if (IsInRange(c0_, 'a', 'z')) { + if (IsInRange(c0_, 'a', 'z') || c0_ == '_') { do { char first_char = static_cast<char>(c0_); Advance<false, false>(); AddLiteralChar(first_char); - } while (IsInRange(c0_, 'a', 'z')); + } while (IsInRange(c0_, 'a', 'z') || c0_ == '_'); if (IsDecimalDigit(c0_) || IsInRange(c0_, 'A', 'Z') || c0_ == '_' || c0_ == '$') { @@ -1483,12 +1539,13 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { return Token::IDENTIFIER; } } else if (c0_ <= kMaxAscii && c0_ != '\\') { - // Only a-z+: could be a keyword or identifier. + // Only a-z+ or _: could be a keyword or identifier. Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal(); Token::Value token = KeywordOrIdentifierToken(chars.start(), chars.length()); if (token == Token::IDENTIFIER || - token == Token::FUTURE_STRICT_RESERVED_WORD) + token == Token::FUTURE_STRICT_RESERVED_WORD || + Token::IsContextualKeyword(token)) literal.Complete(); return token; } @@ -1541,7 +1598,8 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { Token::Value token = KeywordOrIdentifierToken(chars.start(), chars.length()); if (token == Token::IDENTIFIER || - token == Token::FUTURE_STRICT_RESERVED_WORD) + token == Token::FUTURE_STRICT_RESERVED_WORD || + Token::IsContextualKeyword(token)) literal.Complete(); return token; } @@ -1576,8 +1634,8 @@ Token::Value Scanner::ScanIdentifierSuffix(LiteralScope* literal, Token::Value token = KeywordOrIdentifierToken(chars.start(), chars.length()); /* TODO(adamk): YIELD should be handled specially. */ - if (token == Token::IDENTIFIER) { - return Token::IDENTIFIER; + if (token == Token::IDENTIFIER || Token::IsContextualKeyword(token)) { + return token; } else if (token == Token::FUTURE_STRICT_RESERVED_WORD || token == Token::LET || token == Token::STATIC) { return Token::ESCAPED_STRICT_RESERVED_WORD; @@ -1637,6 +1695,7 @@ bool Scanner::ScanRegExpPattern() { literal.Complete(); next_.token = Token::REGEXP_LITERAL; + next_.contextual_token = Token::UNINITIALIZED; return true; } @@ -1658,6 +1717,13 @@ Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() { case 'm': flag = RegExp::kMultiline; break; + case 's': + if (FLAG_harmony_regexp_dotall) { + flag = RegExp::kDotAll; + } else { + return Nothing<RegExp::Flags>(); + } + break; case 'u': flag = RegExp::kUnicode; break; @@ -1678,25 +1744,24 @@ Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() { return Just(RegExp::Flags(flags)); } - -const AstRawString* Scanner::CurrentSymbol(AstValueFactory* ast_value_factory) { +const AstRawString* Scanner::CurrentSymbol( + AstValueFactory* ast_value_factory) const { if (is_literal_one_byte()) { return ast_value_factory->GetOneByteString(literal_one_byte_string()); } return ast_value_factory->GetTwoByteString(literal_two_byte_string()); } - -const AstRawString* Scanner::NextSymbol(AstValueFactory* ast_value_factory) { +const AstRawString* Scanner::NextSymbol( + AstValueFactory* ast_value_factory) const { if (is_next_literal_one_byte()) { return ast_value_factory->GetOneByteString(next_literal_one_byte_string()); } return ast_value_factory->GetTwoByteString(next_literal_two_byte_string()); } - const AstRawString* Scanner::CurrentRawSymbol( - AstValueFactory* ast_value_factory) { + AstValueFactory* ast_value_factory) const { if (is_raw_literal_one_byte()) { return ast_value_factory->GetOneByteString(raw_literal_one_byte_string()); } @@ -1719,13 +1784,12 @@ bool Scanner::ContainsDot() { return std::find(str.begin(), str.end(), '.') != str.end(); } -bool Scanner::FindSymbol(DuplicateFinder* finder) { - // TODO(vogelheim): Move this logic into the calling class; this can be fully - // implemented using the public interface. - if (is_literal_one_byte()) { - return finder->AddOneByteSymbol(literal_one_byte_string()); - } - return finder->AddTwoByteSymbol(literal_two_byte_string()); +bool Scanner::IsDuplicateSymbol(DuplicateFinder* duplicate_finder, + AstValueFactory* ast_value_factory) const { + DCHECK_NOT_NULL(duplicate_finder); + DCHECK_NOT_NULL(ast_value_factory); + const AstRawString* string = CurrentSymbol(ast_value_factory); + return !duplicate_finder->known_symbols_.insert(string).second; } void Scanner::SeekNext(size_t position) { @@ -1736,9 +1800,18 @@ void Scanner::SeekNext(size_t position) { // 1, Reset the current_, next_ and next_next_ tokens // (next_ + next_next_ will be overwrittem by Next(), // current_ will remain unchanged, so overwrite it fully.) - current_ = {{0, 0}, nullptr, nullptr, 0, Token::UNINITIALIZED}; + current_ = {{0, 0}, + nullptr, + nullptr, + 0, + Token::UNINITIALIZED, + MessageTemplate::kNone, + {0, 0}, + Token::UNINITIALIZED}; next_.token = Token::UNINITIALIZED; + next_.contextual_token = Token::UNINITIALIZED; next_next_.token = Token::UNINITIALIZED; + next_next_.contextual_token = Token::UNINITIALIZED; // 2, reset the source to the desired position, source_->Seek(position); // 3, re-scan, by scanning the look-ahead char + 1 token (next_). |