Chromium Code Reviews| 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); |
| } |