summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/scanner.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-06-06 10:28:14 +0200
committerMichaël Zasso <targos@protonmail.com>2017-06-07 10:33:31 +0200
commit3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09 (patch)
tree9dee56e142638b34f1eccbd0ad88c3bce5377c29 /deps/v8/src/parsing/scanner.cc
parent91a1bbe3055a660194ca4d403795aa0c03e9d056 (diff)
downloadnode-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.cc191
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_).