| Index: src/scanner.cc
|
| diff --git a/src/scanner.cc b/src/scanner.cc
|
| index 96459f3c6699ec07f5b3a73db6defd5665dc791e..7cd0895cb3ddb47169b88ed8c1ddf83c3ed4c2a5 100644
|
| --- a/src/scanner.cc
|
| +++ b/src/scanner.cc
|
| @@ -697,13 +697,13 @@ void Scanner::SeekForward(int pos) {
|
| }
|
|
|
|
|
| -template <bool capture_raw>
|
| +template <bool capture_raw, bool in_template_literal>
|
| bool Scanner::ScanEscape() {
|
| uc32 c = c0_;
|
| Advance<capture_raw>();
|
|
|
| // Skip escaped newlines.
|
| - if (c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) {
|
| + if (!in_template_literal && c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) {
|
| // Allow CR+LF newlines in multiline string literals.
|
| if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>();
|
| // Allow LF+CR newlines in multiline string literals.
|
| @@ -725,22 +725,44 @@ bool Scanner::ScanEscape() {
|
| if (c < 0) return false;
|
| break;
|
| }
|
| - case 'v' : c = '\v'; break;
|
| - case 'x' : {
|
| + case 'v':
|
| + c = '\v';
|
| + break;
|
| + case 'x': {
|
| c = ScanHexNumber<capture_raw>(2);
|
| if (c < 0) return false;
|
| break;
|
| }
|
| - case '0' : // fall through
|
| - case '1' : // fall through
|
| - case '2' : // fall through
|
| - case '3' : // fall through
|
| - case '4' : // fall through
|
| - case '5' : // fall through
|
| - case '6' : // fall through
|
| + case '0':
|
| + if (in_template_literal) {
|
| + // \ 0 DecimalDigit is never allowed in templates.
|
| + if (IsDecimalDigit(c0_)) {
|
| + Advance<capture_raw>(); // Advance to include the problematic char.
|
| + return false;
|
| + }
|
| +
|
| + // The TV of TemplateCharacter :: \ EscapeSequence is the CV of
|
| + // EscapeSequence.
|
| + // The CV of EscapeSequence :: 0 is the code unit value 0.
|
| + c = 0;
|
| + break;
|
| + }
|
| + // Fall through.
|
| + case '1': // fall through
|
| + case '2': // fall through
|
| + case '3': // fall through
|
| + case '4': // fall through
|
| + case '5': // fall through
|
| + case '6': // fall through
|
| case '7':
|
| - c = ScanOctalEscape<capture_raw>(c, 2);
|
| - break;
|
| + if (!in_template_literal) {
|
| + c = ScanOctalEscape<capture_raw>(c, 2);
|
| + break;
|
| + }
|
| + // Fall through
|
| + case '8':
|
| + case '9':
|
| + if (in_template_literal) return false;
|
| }
|
|
|
| // According to ECMA-262, section 7.8.4, characters not covered by the
|
| @@ -787,7 +809,7 @@ Token::Value Scanner::ScanString() {
|
| uc32 c = c0_;
|
| Advance();
|
| if (c == '\\') {
|
| - if (c0_ < 0 || !ScanEscape<false>()) return Token::ILLEGAL;
|
| + if (c0_ < 0 || !ScanEscape<false, false>()) return Token::ILLEGAL;
|
| } else {
|
| AddLiteralChar(c);
|
| }
|
| @@ -818,6 +840,7 @@ Token::Value Scanner::ScanTemplateSpan() {
|
| LiteralScope literal(this);
|
| StartRawLiteral();
|
| const bool capture_raw = true;
|
| + const bool in_template_literal = true;
|
|
|
| while (true) {
|
| uc32 c = c0_;
|
| @@ -844,11 +867,8 @@ Token::Value Scanner::ScanTemplateSpan() {
|
| AddRawLiteralChar('\n');
|
| }
|
| }
|
| - } else if (c0_ == '0') {
|
| - Advance<capture_raw>();
|
| - AddLiteralChar('0');
|
| - } else {
|
| - ScanEscape<true>();
|
| + } else if (!ScanEscape<capture_raw, in_template_literal>()) {
|
| + return Token::ILLEGAL;
|
| }
|
| } else if (c < 0) {
|
| // Unterminated template literal
|
|
|