Index: src/parsing/parser-base.h |
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h |
index 5e6922206748b5f4976672461b314a244d67ea03..b90344e82820989ef8bf1efed3ba099ad27d8022 100644 |
--- a/src/parsing/parser-base.h |
+++ b/src/parsing/parser-base.h |
@@ -226,7 +226,8 @@ class ParserBase { |
allow_harmony_class_fields_(false), |
allow_harmony_object_rest_spread_(false), |
allow_harmony_dynamic_import_(false), |
- allow_harmony_async_iteration_(false) {} |
+ allow_harmony_async_iteration_(false), |
+ allow_harmony_template_escapes_(false) {} |
#define ALLOW_ACCESSORS(name) \ |
bool allow_##name() const { return allow_##name##_; } \ |
@@ -242,6 +243,7 @@ class ParserBase { |
ALLOW_ACCESSORS(harmony_object_rest_spread); |
ALLOW_ACCESSORS(harmony_dynamic_import); |
ALLOW_ACCESSORS(harmony_async_iteration); |
+ ALLOW_ACCESSORS(harmony_template_escapes); |
#undef ALLOW_ACCESSORS |
@@ -816,14 +818,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(); |
@@ -834,12 +834,23 @@ class ParserBase { |
} |
} |
- inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
- CheckOctalLiteral(beg_pos, end_pos, false, ok); |
- } |
+ // Checks if an octal literal or an invalid hex or unicode escape sequence |
+ // appears in a template literal. In the presence of such, either |
+ // returns false or reports an error, depending on should_throw. Otherwise |
+ // returns true. |
+ inline bool CheckTemplateEscapes(bool should_throw, bool* ok) { |
+ if (!scanner()->has_invalid_template_escape()) { |
+ return true; |
+ } |
- inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
- CheckOctalLiteral(beg_pos, end_pos, true, ok); |
+ // Handle error case(s) |
+ if (should_throw) { |
+ impl()->ReportMessageAt(scanner()->invalid_template_escape_location(), |
+ scanner()->invalid_template_escape_message()); |
+ *ok = false; |
+ } |
+ scanner()->clear_invalid_template_escape(); |
+ return false; |
} |
void CheckDestructuringElement(ExpressionT element, int beg_pos, int end_pos); |
@@ -1138,7 +1149,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); |
@@ -1449,6 +1461,7 @@ class ParserBase { |
bool allow_harmony_object_rest_spread_; |
bool allow_harmony_dynamic_import_; |
bool allow_harmony_async_iteration_; |
+ bool allow_harmony_template_escapes_; |
friend class DiscardableZoneScope; |
}; |
@@ -1817,7 +1830,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) { |
@@ -3215,7 +3228,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; |
} |
@@ -3495,7 +3508,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: { |
@@ -4376,7 +4389,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. |
@@ -4389,22 +4402,25 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( |
// TEMPLATE_SPAN, or a TEMPLATE_TAIL. |
CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL); |
+ bool forbid_illegal_escapes = !allow_harmony_template_escapes() || !tagged; |
+ |
// 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); |
+ bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes, CHECK_OK); |
+ impl()->AddTemplateSpan(&ts, is_valid, true); |
return impl()->CloseTemplateLiteral(&ts, start, tag); |
} |
Consume(Token::TEMPLATE_SPAN); |
int pos = position(); |
typename Impl::TemplateLiteralState ts = impl()->OpenTemplateLiteral(pos); |
- impl()->AddTemplateSpan(&ts, false); |
+ bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes, CHECK_OK); |
+ impl()->AddTemplateSpan(&ts, is_valid, false); |
Token::Value next; |
// If we open with a TEMPLATE_SPAN, we must scan the subsequent expression, |
@@ -4412,7 +4428,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()), |
@@ -4458,11 +4473,11 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( |
return impl()->EmptyExpression(); |
} |
- impl()->AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL); |
+ bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes, CHECK_OK); |
+ impl()->AddTemplateSpan(&ts, is_valid, 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); |
} |