Index: src/parsing/parser-base.h |
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h |
index 9809071d4789a58da84abfd32420688e0fd2a038..71e7f7412946eb843b5a5be4752cf990aab1e708 100644 |
--- a/src/parsing/parser-base.h |
+++ b/src/parsing/parser-base.h |
@@ -225,7 +225,8 @@ class ParserBase { |
allow_harmony_trailing_commas_(false), |
allow_harmony_class_fields_(false), |
allow_harmony_object_rest_spread_(false), |
- allow_harmony_dynamic_import_(false) {} |
+ allow_harmony_dynamic_import_(false), |
+ allow_harmony_template_escapes_(false) {} |
#define ALLOW_ACCESSORS(name) \ |
bool allow_##name() const { return allow_##name##_; } \ |
@@ -240,6 +241,7 @@ class ParserBase { |
ALLOW_ACCESSORS(harmony_class_fields); |
ALLOW_ACCESSORS(harmony_object_rest_spread); |
ALLOW_ACCESSORS(harmony_dynamic_import); |
+ ALLOW_ACCESSORS(harmony_template_escapes); |
#undef ALLOW_ACCESSORS |
@@ -864,14 +866,12 @@ class ParserBase { |
} |
// Checks whether an octal literal was last seen between beg_pos and end_pos. |
- // If so, reports an error. Only called for strict mode and template strings. |
- void CheckOctalLiteral(int beg_pos, int end_pos, bool is_template, bool* ok) { |
+ // Only called for strict mode strings. |
+ void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
Scanner::Location octal = scanner()->octal_position(); |
if (octal.IsValid() && beg_pos <= octal.beg_pos && |
octal.end_pos <= end_pos) { |
- MessageTemplate::Template message = |
- is_template ? MessageTemplate::kTemplateOctalLiteral |
- : scanner()->octal_message(); |
+ MessageTemplate::Template message = scanner()->octal_message(); |
DCHECK_NE(message, MessageTemplate::kNone); |
impl()->ReportMessageAt(octal, message); |
scanner()->clear_octal_position(); |
@@ -882,12 +882,35 @@ class ParserBase { |
} |
} |
- inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
- CheckOctalLiteral(beg_pos, end_pos, false, ok); |
- } |
- |
- inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
- CheckOctalLiteral(beg_pos, end_pos, true, ok); |
+ // Checks if an octal literal or an invalid hex or unicode escape sequence |
+ // appears between beg_pos and end_pos. In the presence of such, either |
+ // returns false or reports an error, depending on dont_throw. Otherwise |
+ // returns true. |
+ inline bool CheckTemplateEscapes(int beg_pos, int end_pos, bool dont_throw, |
+ bool* ok) { |
+ Scanner::Location octal = scanner()->octal_position(); |
+ if (octal.IsValid() && beg_pos <= octal.beg_pos && |
+ octal.end_pos <= end_pos) { |
+ if (dont_throw) { |
+ scanner()->clear_octal_position(); |
+ return false; |
+ } |
+ MessageTemplate::Template message = |
+ MessageTemplate::kTemplateOctalLiteral; |
+ impl()->ReportMessageAt(octal, message); |
+ scanner()->clear_octal_position(); |
+ *ok = false; |
+ } else if (scanner()->has_invalid_template_escape()) { |
+ if (dont_throw) { |
+ scanner()->clear_invalid_template_escape(); |
+ return false; |
+ } |
+ impl()->ReportMessageAt(scanner()->invalid_template_escape_location(), |
+ scanner()->invalid_template_escape_message()); |
+ scanner()->clear_invalid_template_escape(); |
+ *ok = false; |
+ } |
+ return true; |
} |
void CheckDestructuringElement(ExpressionT element, int beg_pos, int end_pos); |
@@ -1194,7 +1217,8 @@ class ParserBase { |
Scanner::Location class_name_location, |
bool name_is_strict_reserved, |
int class_token_pos, bool* ok); |
- ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok); |
+ ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool tagged, |
+ bool* ok); |
ExpressionT ParseSuperExpression(bool is_new, bool* ok); |
ExpressionT ParseDynamicImportExpression(bool* ok); |
ExpressionT ParseNewTargetExpression(bool* ok); |
@@ -1503,6 +1527,7 @@ class ParserBase { |
bool allow_harmony_class_fields_; |
bool allow_harmony_object_rest_spread_; |
bool allow_harmony_dynamic_import_; |
+ bool allow_harmony_template_escapes_; |
friend class DiscardableZoneScope; |
}; |
@@ -1873,7 +1898,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression( |
case Token::TEMPLATE_SPAN: |
case Token::TEMPLATE_TAIL: |
BindingPatternUnexpectedToken(); |
- return ParseTemplateLiteral(impl()->NoTemplateTag(), beg_pos, ok); |
+ return ParseTemplateLiteral(impl()->NoTemplateTag(), beg_pos, false, ok); |
case Token::MOD: |
if (allow_natives() || extension_ != NULL) { |
@@ -3294,7 +3319,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) { |
impl()->RewriteNonPattern(CHECK_OK); |
BindingPatternUnexpectedToken(); |
ArrowFormalParametersUnexpectedToken(); |
- result = ParseTemplateLiteral(result, position(), CHECK_OK); |
+ result = ParseTemplateLiteral(result, position(), true, CHECK_OK); |
break; |
} |
@@ -3569,7 +3594,7 @@ ParserBase<Impl>::ParseMemberExpressionContinuation(ExpressionT expression, |
expression->AsFunctionLiteral()->SetShouldEagerCompile(); |
} |
} |
- expression = ParseTemplateLiteral(expression, pos, CHECK_OK); |
+ expression = ParseTemplateLiteral(expression, pos, true, CHECK_OK); |
break; |
} |
case Token::ILLEGAL: { |
@@ -4455,7 +4480,7 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral(bool* ok) { |
template <typename Impl> |
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( |
- ExpressionT tag, int start, bool* ok) { |
+ ExpressionT tag, int start, bool tagged, bool* ok) { |
// A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal |
// text followed by a substitution expression), finalized by a single |
// TEMPLATE_TAIL. |
@@ -4468,22 +4493,28 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( |
// TEMPLATE_SPAN, or a TEMPLATE_TAIL. |
CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL); |
+ bool allow_illegal_escapes = tagged && allow_harmony_template_escapes(); |
+ bool should_cook = true; |
+ |
// If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate. |
// In this case we may simply consume the token and build a template with a |
// single TEMPLATE_SPAN and no expressions. |
if (peek() == Token::TEMPLATE_TAIL) { |
Consume(Token::TEMPLATE_TAIL); |
int pos = position(); |
- CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK); |
typename Impl::TemplateLiteralState ts = impl()->OpenTemplateLiteral(pos); |
- impl()->AddTemplateSpan(&ts, true); |
+ should_cook = CheckTemplateEscapes(pos, peek_position(), |
+ allow_illegal_escapes, CHECK_OK); |
+ impl()->AddTemplateSpan(&ts, should_cook, true); |
return impl()->CloseTemplateLiteral(&ts, start, tag); |
} |
Consume(Token::TEMPLATE_SPAN); |
int pos = position(); |
+ should_cook = CheckTemplateEscapes(pos, peek_position(), |
+ allow_illegal_escapes, CHECK_OK); |
typename Impl::TemplateLiteralState ts = impl()->OpenTemplateLiteral(pos); |
- impl()->AddTemplateSpan(&ts, false); |
+ impl()->AddTemplateSpan(&ts, should_cook, false); |
Token::Value next; |
// If we open with a TEMPLATE_SPAN, we must scan the subsequent expression, |
@@ -4491,7 +4522,6 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( |
// case, representing a TemplateMiddle). |
do { |
- CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK); |
next = peek(); |
if (next == Token::EOS) { |
impl()->ReportMessageAt(Scanner::Location(start, peek_position()), |
@@ -4537,11 +4567,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( |
return impl()->EmptyExpression(); |
} |
- impl()->AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL); |
+ should_cook = CheckTemplateEscapes(pos, peek_position(), |
+ allow_illegal_escapes, CHECK_OK); |
+ impl()->AddTemplateSpan(&ts, should_cook, next == Token::TEMPLATE_TAIL); |
} while (next == Token::TEMPLATE_SPAN); |
DCHECK_EQ(next, Token::TEMPLATE_TAIL); |
- CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK); |
// Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral. |
return impl()->CloseTemplateLiteral(&ts, start, tag); |
} |