| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index b2cf3b1a6d385ee7d79b9b46bcda1dc2dd209346..c6fe2b44ef3df95b73a5b61eb4b6f51634cc84c9 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -802,6 +802,7 @@ Parser::Parser(CompilationInfo* info, ParseInfo* parse_info)
|
| set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
|
| set_allow_classes(FLAG_harmony_classes);
|
| set_allow_harmony_object_literals(FLAG_harmony_object_literals);
|
| + set_allow_harmony_templates(FLAG_harmony_templates);
|
| for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
|
| ++feature) {
|
| use_counts_[feature] = 0;
|
| @@ -3882,6 +3883,7 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
|
| reusable_preparser_->set_allow_classes(allow_classes());
|
| reusable_preparser_->set_allow_harmony_object_literals(
|
| allow_harmony_object_literals());
|
| + reusable_preparser_->set_allow_harmony_templates(allow_harmony_templates());
|
| }
|
| PreParser::PreParseResult result =
|
| reusable_preparser_->PreParseLazyFunction(strict_mode(),
|
| @@ -5084,4 +5086,141 @@ void Parser::ParseOnBackground() {
|
| log_ = NULL;
|
| }
|
| }
|
| +
|
| +
|
| +ParserTraits::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
|
| + return new (zone()) ParserTraits::TemplateLiteral(zone(), pos);
|
| +}
|
| +
|
| +
|
| +void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) {
|
| + int pos = scanner()->location().beg_pos;
|
| + int end = scanner()->location().end_pos - (tail ? 1 : 2);
|
| + const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
|
| + Literal* cooked = factory()->NewStringLiteral(tv, pos);
|
| + (*state)->AddTemplateSpan(cooked, end, zone());
|
| +}
|
| +
|
| +
|
| +void Parser::AddTemplateExpression(TemplateLiteralState* state,
|
| + Expression* expression) {
|
| + (*state)->AddExpression(expression, zone());
|
| +}
|
| +
|
| +
|
| +Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
|
| + Expression* tag) {
|
| + TemplateLiteral* lit = *state;
|
| + int pos = lit->position();
|
| + const ZoneList<Expression*>* cooked_strings = lit->cooked();
|
| + const ZoneList<Expression*>* expressions = lit->expressions();
|
| + CHECK(cooked_strings->length() == (expressions->length() + 1));
|
| +
|
| + if (!tag) {
|
| + // Build tree of BinaryOps to simplify code-generation
|
| + Expression* expr = NULL;
|
| +
|
| + if (expressions->length() == 0) {
|
| + // Simple case: treat as string literal
|
| + expr = cooked_strings->at(0);
|
| + } else {
|
| + int i;
|
| + Expression* cooked_str = cooked_strings->at(0);
|
| + expr = factory()->NewBinaryOperation(
|
| + Token::ADD, cooked_str, expressions->at(0), cooked_str->position());
|
| + for (i = 1; i < expressions->length(); ++i) {
|
| + cooked_str = cooked_strings->at(i);
|
| + expr = factory()->NewBinaryOperation(
|
| + Token::ADD, expr, factory()->NewBinaryOperation(
|
| + Token::ADD, cooked_str, expressions->at(i),
|
| + cooked_str->position()),
|
| + cooked_str->position());
|
| + }
|
| + cooked_str = cooked_strings->at(i);
|
| + expr = factory()->NewBinaryOperation(Token::ADD, expr, cooked_str,
|
| + cooked_str->position());
|
| + }
|
| + return expr;
|
| + } else {
|
| + ZoneList<Expression*>* raw_strings = TemplateRawStrings(lit);
|
| + Handle<String> source(String::cast(script()->source()));
|
| +
|
| + int cooked_idx = function_state_->NextMaterializedLiteralIndex();
|
| + int raw_idx = function_state_->NextMaterializedLiteralIndex();
|
| +
|
| + // GetTemplateCallSite
|
| + ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
|
| + args->Add(factory()->NewArrayLiteral(
|
| + const_cast<ZoneList<Expression*>*>(cooked_strings),
|
| + cooked_idx, pos),
|
| + zone());
|
| + args->Add(
|
| + factory()->NewArrayLiteral(
|
| + const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos),
|
| + zone());
|
| + this->CheckPossibleEvalCall(tag, scope_);
|
| + Expression* call_site = factory()->NewCallRuntime(
|
| + ast_value_factory()->get_template_callsite_string(), NULL, args, start);
|
| +
|
| + // Call TagFn
|
| + ZoneList<Expression*>* call_args =
|
| + new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone());
|
| + call_args->Add(call_site, zone());
|
| + call_args->AddAll(*expressions, zone());
|
| + return factory()->NewCall(tag, call_args, pos);
|
| + }
|
| +}
|
| +
|
| +
|
| +ZoneList<Expression*>* Parser::TemplateRawStrings(const TemplateLiteral* lit) {
|
| + const ZoneList<int>* lengths = lit->lengths();
|
| + const ZoneList<Expression*>* cooked_strings = lit->cooked();
|
| + int total = lengths->length();
|
| + ZoneList<Expression*>* raw_strings;
|
| +
|
| + // Given a TemplateLiteral, produce a list of raw strings, used for generating
|
| + // a CallSite object for a tagged template invocations.
|
| + //
|
| + // A raw string will consist of the unescaped characters of a template span,
|
| + // with end-of-line sequences normalized to U+000A LINE FEEDs, and without
|
| + // leading or trailing template delimiters.
|
| + //
|
| +
|
| + DCHECK(total);
|
| +
|
| + Handle<String> source(String::cast(script()->source()));
|
| +
|
| + raw_strings = new (zone()) ZoneList<Expression*>(total, zone());
|
| +
|
| + for (int index = 0; index < total; ++index) {
|
| + int span_start = cooked_strings->at(index)->position() + 1;
|
| + int span_end = lengths->at(index) - 1;
|
| + int length;
|
| + int to_index = 0;
|
| +
|
| + SmartArrayPointer<char> raw_chars =
|
| + source->ToCString(ALLOW_NULLS, FAST_STRING_TRAVERSAL, span_start,
|
| + span_end, &length);
|
| +
|
| + // Normalize raw line-feeds. [U+000D U+000A] (CRLF) and [U+000D] (CR) must
|
| + // be translated into U+000A (LF).
|
| + for (int from_index = 0; from_index < length; ++from_index) {
|
| + char ch = raw_chars[from_index];
|
| + if (ch == '\r') {
|
| + ch = '\n';
|
| + if (from_index + 1 < length && raw_chars[from_index + 1] == '\n') {
|
| + ++from_index;
|
| + }
|
| + }
|
| + raw_chars[to_index++] = ch;
|
| + }
|
| +
|
| + const AstRawString* raw_str = ast_value_factory()->GetOneByteString(
|
| + OneByteVector(raw_chars.get(), to_index));
|
| + Literal* raw_lit = factory()->NewStringLiteral(raw_str, span_start - 1);
|
| + raw_strings->Add(raw_lit, zone());
|
| + }
|
| +
|
| + return raw_strings;
|
| +}
|
| } } // namespace v8::internal
|
|
|