Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index 7fc5dd0512b4ba73be38148b35a9faaffc63be8a..7bf7541bc81338169d490f35661fa8b0fcae4fa7 100644 |
| --- a/src/parser.cc |
| +++ b/src/parser.cc |
| @@ -813,6 +813,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; |
| @@ -3907,6 +3908,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(), |
| @@ -5025,4 +5027,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) { |
| +#define COOKED_STRING(i) cooked_strings->at(i) |
|
rossberg
2014/11/14 12:28:07
Nit: please remove these macros, they don't seem w
|
| +#define POS(i) cooked_strings->at(i)->position() |
| +#define EXPR(i) expressions->at(i) |
| + 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_STRING(0); |
| + } else { |
| + int i; |
| + expr = factory()->NewBinaryOperation(Token::ADD, |
| + COOKED_STRING(0), EXPR(0), POS(0)); |
| + for (i = 1; i < expressions->length(); ++i) { |
| + expr = factory()->NewBinaryOperation(Token::ADD, |
| + expr, factory()->NewBinaryOperation(Token::ADD, COOKED_STRING(i), |
| + EXPR(i), POS(i)), POS(i)); |
|
rossberg
2014/11/14 12:28:07
Nit: indentation?
|
| + } |
| + expr = factory()->NewBinaryOperation(Token::ADD, expr, COOKED_STRING(i), |
| + POS(i)); |
| + } |
| + 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* expr = factory()->NewCallRuntime( |
|
rossberg
2014/11/14 12:28:07
Nit: rename from 'expr' to 'call_site'
|
| + 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(expr, zone()); |
| + call_args->AddAll(*expressions, zone()); |
| + expr = factory()->NewCall(tag, call_args, pos); |
| + return expr; |
| + } |
| +#undef COOKED_STRING |
| +#undef POS |
| +#undef EXPR |
| +} |
| + |
| + |
| +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; |
| + SmartArrayPointer<char> raw_chars; |
| + |
| + // 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; |
| + |
| + 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') { |
| + if (raw_chars[from_index + 1] == '\n') { |
|
rossberg
2014/11/14 12:28:07
Perhaps add a comment explaining that it is actual
caitp (gmail)
2014/11/14 13:25:18
Hmm, I'm not sure this is guaranteed to be safe, a
|
| + ++from_index; |
| + } |
| + ch = '\n'; |
|
rossberg
2014/11/14 12:28:07
Nit: put this first.
|
| + } |
| + 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 |