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 |