Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Unified Diff: src/parsing/parser-base.h

Issue 2665513002: [parser] Lift template literal invalid escape restriction (Closed)
Patch Set: rebase harder Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/parsing/parser-base.h
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
index 56b40abf987917ad7df9b94180daacba8597ad24..211809b4b67826b49f2bf71cc8bd8a2da0949312 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
@@ -875,14 +877,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();
@@ -893,12 +893,34 @@ 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_error()) {
+ if (dont_throw) {
+ scanner()->clear_error();
+ return false;
+ }
+ impl()->ReportMessageAt(scanner()->error_location(), scanner()->error());
+ scanner()->clear_error();
+ *ok = false;
+ }
+ return true;
}
void CheckDestructuringElement(ExpressionT element, int beg_pos, int end_pos);
@@ -1205,6 +1227,7 @@ class ParserBase {
Scanner::Location class_name_location,
bool name_is_strict_reserved,
int class_token_pos, bool* ok);
+ template <bool tagged>
vogelheim 2017/02/13 17:36:06 Why is this a template parameter, rather than a re
bakkot1 2017/02/13 20:22:24 I default to using template parameters for statica
ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok);
ExpressionT ParseSuperExpression(bool is_new, bool* ok);
ExpressionT ParseDynamicImportExpression(bool* ok);
@@ -1487,6 +1510,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;
};
@@ -1856,7 +1880,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<false>(impl()->NoTemplateTag(), beg_pos, ok);
case Token::MOD:
if (allow_natives() || extension_ != NULL) {
@@ -3277,7 +3301,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
impl()->RewriteNonPattern(CHECK_OK);
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
- result = ParseTemplateLiteral(result, position(), CHECK_OK);
+ result = ParseTemplateLiteral<true>(result, position(), CHECK_OK);
break;
}
@@ -3552,7 +3576,7 @@ ParserBase<Impl>::ParseMemberExpressionContinuation(ExpressionT expression,
expression->AsFunctionLiteral()->SetShouldEagerCompile();
}
}
- expression = ParseTemplateLiteral(expression, pos, CHECK_OK);
+ expression = ParseTemplateLiteral<true>(expression, pos, CHECK_OK);
break;
}
case Token::ILLEGAL: {
@@ -4444,6 +4468,7 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral(bool* ok) {
}
template <typename Impl>
+template <bool tagged>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
ExpressionT tag, int start, bool* ok) {
// A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
@@ -4458,22 +4483,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,
@@ -4481,7 +4512,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()),
@@ -4527,11 +4557,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);
}

Powered by Google App Engine
This is Rietveld 408576698