| Index: src/scanner.cc | 
| diff --git a/src/scanner.cc b/src/scanner.cc | 
| index 0709939dbac8b142a3ad81a2ea948fa681179b34..a95ce9256ea0c38ed457c4473dc3d6470b8f3559 100644 | 
| --- a/src/scanner.cc | 
| +++ b/src/scanner.cc | 
| @@ -54,7 +54,7 @@ void Scanner::Initialize(Utf16CharacterStream* source) { | 
| } | 
|  | 
|  | 
| -uc32 Scanner::ScanHexNumber(int expected_length) { | 
| +uc32 Scanner::ScanHexNumber(int expected_length, bool recordRaw) { | 
| DCHECK(expected_length <= 4);  // prevent overflow | 
|  | 
| uc32 digits[4] = { 0, 0, 0, 0 }; | 
| @@ -74,6 +74,9 @@ uc32 Scanner::ScanHexNumber(int expected_length) { | 
| return -1; | 
| } | 
| x = x * 16 + d; | 
| +    if (recordRaw) { | 
| +      AddRawLiteralChar(c0_); | 
| +    } | 
| Advance(); | 
| } | 
|  | 
| @@ -411,7 +414,9 @@ Token::Value Scanner::ScanHtmlComment() { | 
|  | 
| void Scanner::Scan() { | 
| next_.literal_chars = NULL; | 
| +  next_.raw_literal_chars = NULL; | 
| Token::Value token; | 
| + | 
| do { | 
| // Remember the position of the next token | 
| next_.location.beg_pos = source_pos(); | 
| @@ -634,6 +639,12 @@ void Scanner::Scan() { | 
| token = Select(Token::BIT_NOT); | 
| break; | 
|  | 
| +      case '`': | 
| +        if (HarmonyTemplates()) { | 
| +          token = ScanTemplateSpan(); | 
| +          break; | 
| +        } | 
| + | 
| default: | 
| if (unicode_cache_->IsIdentifierStart(c0_)) { | 
| token = ScanIdentifierOrKeyword(); | 
| @@ -679,7 +690,7 @@ void Scanner::SeekForward(int pos) { | 
| } | 
|  | 
|  | 
| -bool Scanner::ScanEscape() { | 
| +bool Scanner::ScanEscape(bool recordRaw) { | 
| uc32 c = c0_; | 
| Advance(); | 
|  | 
| @@ -702,13 +713,13 @@ bool Scanner::ScanEscape() { | 
| case 'r' : c = '\r'; break; | 
| case 't' : c = '\t'; break; | 
| case 'u' : { | 
| -      c = ScanHexNumber(4); | 
| +      c = ScanHexNumber(4, recordRaw); | 
| if (c < 0) return false; | 
| break; | 
| } | 
| case 'v' : c = '\v'; break; | 
| case 'x' : { | 
| -      c = ScanHexNumber(2); | 
| +      c = ScanHexNumber(2, recordRaw); | 
| if (c < 0) return false; | 
| break; | 
| } | 
| @@ -719,7 +730,9 @@ bool Scanner::ScanEscape() { | 
| case '4' :  // fall through | 
| case '5' :  // fall through | 
| case '6' :  // fall through | 
| -    case '7' : c = ScanOctalEscape(c, 2); break; | 
| +    case '7': | 
| +      c = ScanOctalEscape(c, 2, recordRaw); | 
| +      break; | 
| } | 
|  | 
| // According to ECMA-262, section 7.8.4, characters not covered by the | 
| @@ -732,7 +745,7 @@ bool Scanner::ScanEscape() { | 
|  | 
| // Octal escapes of the forms '\0xx' and '\xxx' are not a part of | 
| // ECMA-262. Other JS VMs support them. | 
| -uc32 Scanner::ScanOctalEscape(uc32 c, int length) { | 
| +uc32 Scanner::ScanOctalEscape(uc32 c, int length, bool recordRaw) { | 
| uc32 x = c - '0'; | 
| int i = 0; | 
| for (; i < length; i++) { | 
| @@ -741,6 +754,9 @@ uc32 Scanner::ScanOctalEscape(uc32 c, int length) { | 
| int nx = x * 8 + d; | 
| if (nx >= 256) break; | 
| x = nx; | 
| +    if (recordRaw) { | 
| +      AddRawLiteralChar(c0_); | 
| +    } | 
| Advance(); | 
| } | 
| // Anything except '\0' is an octal escape sequence, illegal in strict mode. | 
| @@ -778,6 +794,55 @@ Token::Value Scanner::ScanString() { | 
| } | 
|  | 
|  | 
| +Token::Value Scanner::ScanTemplateSpan() { | 
| +  if (next_.token == Token::RBRACE) { | 
| +    PushBack('}'); | 
| +  } | 
| +  next_.location.beg_pos = source_pos(); | 
| +  Token::Value result = Token::ILLEGAL; | 
| +  DCHECK(c0_ == '`' || c0_ == '}'); | 
| +  Advance();  // Consume ` or } | 
| + | 
| +  LiteralScope literal(this); | 
| +  while (true) { | 
| +    uc32 c = c0_; | 
| +    Advance(); | 
| +    if (c == '`') { | 
| +      result = Token::TEMPLATE_TAIL; | 
| +      break; | 
| +    } else if (c == '$' && c0_ == '{') { | 
| +      Advance();  // Consume '{' | 
| +      result = Token::TEMPLATE_SPAN; | 
| +      break; | 
| +    } else if (c == '\\') { | 
| +      if (unicode_cache_->IsLineTerminator(c0_)) { | 
| +        // The TV of LineContinuation :: \ LineTerminatorSequence is the empty | 
| +        // code unit sequence. | 
| +        do { | 
| +          uc32 lastChar = c0_; | 
| +          Advance(); | 
| +          if (lastChar == '\r' && c0_ == '\n') Advance(); | 
| +          AddRawLiteralChar('\n'); | 
| +        } while (unicode_cache_->IsLineTerminator(c0_)); | 
| +      } else { | 
| +        ScanEscape(); | 
| +      } | 
| +    } else if (c < 0) { | 
| +      // Unterminated template literal | 
| +      PushBack(c); | 
| +      break; | 
| +    } else { | 
| +      AddLiteralChar(c); | 
| +      AddRawLiteralChar(c); | 
| +    } | 
| +  } | 
| +  literal.Complete(); | 
| +  next_.location.end_pos = source_pos(); | 
| +  next_.token = result; | 
| +  return result; | 
| +} | 
| + | 
| + | 
| void Scanner::ScanDecimalDigits() { | 
| while (IsDecimalDigit(c0_)) | 
| AddLiteralCharAdvance(); | 
| @@ -1201,6 +1266,15 @@ const AstRawString* Scanner::CurrentSymbol(AstValueFactory* ast_value_factory) { | 
| } | 
|  | 
|  | 
| +const AstRawString* Scanner::CurrentRawSymbol( | 
| +    AstValueFactory* ast_value_factory) { | 
| +  if (is_raw_one_byte()) { | 
| +    return ast_value_factory->GetOneByteString(raw_one_byte_string()); | 
| +  } | 
| +  return ast_value_factory->GetTwoByteString(raw_two_byte_string()); | 
| +} | 
| + | 
| + | 
| const AstRawString* Scanner::NextSymbol(AstValueFactory* ast_value_factory) { | 
| if (is_next_literal_one_byte()) { | 
| return ast_value_factory->GetOneByteString(next_literal_one_byte_string()); | 
| @@ -1209,6 +1283,14 @@ const AstRawString* Scanner::NextSymbol(AstValueFactory* ast_value_factory) { | 
| } | 
|  | 
|  | 
| +const AstRawString* Scanner::NextRawSymbol(AstValueFactory* ast_value_factory) { | 
| +  if (is_next_raw_one_byte()) { | 
| +    return ast_value_factory->GetOneByteString(next_raw_one_byte_string()); | 
| +  } | 
| +  return ast_value_factory->GetTwoByteString(next_raw_two_byte_string()); | 
| +} | 
| + | 
| + | 
| double Scanner::DoubleValue() { | 
| DCHECK(is_literal_one_byte()); | 
| return StringToDouble( | 
|  |