Commit edf3dab4 authored by arv's avatar arv Committed by Commit bot

ES6 template literals: Fix issue with template after rbrace

If we hade }` the right brace was always treated as part of the
template literal. We should only treat the right brace as part of
the literal when we continue to parse the template literal after a
placeholder.

BUG=v8:3734
LOG=Y

Review URL: https://codereview.chromium.org/778813003

Cr-Commit-Position: refs/heads/master@{#25661}
parent f5a027dc
...@@ -2851,7 +2851,7 @@ ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) { ...@@ -2851,7 +2851,7 @@ ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, bool* ok) {
// If we didn't die parsing that expression, our next token should be a // If we didn't die parsing that expression, our next token should be a
// TEMPLATE_SPAN or TEMPLATE_TAIL. // TEMPLATE_SPAN or TEMPLATE_TAIL.
next = scanner()->ScanTemplateSpan(); next = scanner()->ScanTemplateContinuation();
Next(); Next();
if (!next) { if (!next) {
......
...@@ -647,7 +647,7 @@ void Scanner::Scan() { ...@@ -647,7 +647,7 @@ void Scanner::Scan() {
case '`': case '`':
if (HarmonyTemplates()) { if (HarmonyTemplates()) {
token = ScanTemplateSpan(); token = ScanTemplateStart();
break; break;
} }
...@@ -808,19 +808,8 @@ Token::Value Scanner::ScanTemplateSpan() { ...@@ -808,19 +808,8 @@ Token::Value Scanner::ScanTemplateSpan() {
// A TEMPLATE_SPAN should always be followed by an Expression, while a // A TEMPLATE_SPAN should always be followed by an Expression, while a
// TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be
// followed by an Expression. // followed by an Expression.
//
if (next_.token == Token::RBRACE) {
// After parsing an Expression, the source position is incorrect due to
// having scanned the brace. Push the RBRACE back into the stream.
PushBack('}');
}
next_.location.beg_pos = source_pos();
Token::Value result = Token::TEMPLATE_SPAN; Token::Value result = Token::TEMPLATE_SPAN;
DCHECK(c0_ == '`' || c0_ == '}');
Advance(); // Consume ` or }
LiteralScope literal(this, true); LiteralScope literal(this, true);
while (true) { while (true) {
...@@ -881,6 +870,21 @@ Token::Value Scanner::ScanTemplateSpan() { ...@@ -881,6 +870,21 @@ Token::Value Scanner::ScanTemplateSpan() {
} }
Token::Value Scanner::ScanTemplateStart() {
DCHECK(c0_ == '`');
next_.location.beg_pos = source_pos();
Advance(); // Consume `
return ScanTemplateSpan();
}
Token::Value Scanner::ScanTemplateContinuation() {
DCHECK_EQ(next_.token, Token::RBRACE);
next_.location.beg_pos = source_pos() - 1; // We already consumed }
return ScanTemplateSpan();
}
void Scanner::ScanDecimalDigits() { void Scanner::ScanDecimalDigits() {
while (IsDecimalDigit(c0_)) while (IsDecimalDigit(c0_))
AddLiteralCharAdvance(); AddLiteralCharAdvance();
......
...@@ -484,7 +484,8 @@ class Scanner { ...@@ -484,7 +484,8 @@ class Scanner {
bool ScanRegExpFlags(); bool ScanRegExpFlags();
// Scans the input as a template literal // Scans the input as a template literal
Token::Value ScanTemplateSpan(); Token::Value ScanTemplateStart();
Token::Value ScanTemplateContinuation();
const LiteralBuffer* source_url() const { return &source_url_; } const LiteralBuffer* source_url() const { return &source_url_; }
const LiteralBuffer* source_mapping_url() const { const LiteralBuffer* source_mapping_url() const {
...@@ -692,6 +693,8 @@ class Scanner { ...@@ -692,6 +693,8 @@ class Scanner {
// Helper for the above functions. // Helper for the above functions.
uc32 ScanUnicodeEscape(); uc32 ScanUnicodeEscape();
Token::Value ScanTemplateSpan();
// Return the current source position. // Return the current source position.
int source_pos() { int source_pos() {
return source_->pos() - kCharacterLookaheadBufferSize; return source_->pos() - kCharacterLookaheadBufferSize;
......
...@@ -453,3 +453,21 @@ var obj = { ...@@ -453,3 +453,21 @@ var obj = {
assertEquals(`a\u{62}c`, "abc"); assertEquals(`a\u{62}c`, "abc");
assertEquals(`a\u{000062}c`, "abc"); assertEquals(`a\u{000062}c`, "abc");
})(); })();
(function testLiteralAfterRightBrace() {
// Regression test for https://code.google.com/p/v8/issues/detail?id=3734
function f() {}
`abc`;
function g() {}`def`;
{
// block
}
`ghi`;
{
// block
}`jkl`;
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment