Commit 6fcc22dc authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

[es6] call ToString() on template substitutions

BUG=v8:3980
R=arv@chromium.org
LOG=N

Review URL: https://codereview.chromium.org/1027183002

Cr-Commit-Position: refs/heads/master@{#27402}
parent e62f754d
...@@ -261,6 +261,7 @@ class AstValue : public ZoneObject { ...@@ -261,6 +261,7 @@ class AstValue : public ZoneObject {
F(prototype, "prototype") \ F(prototype, "prototype") \
F(this, "this") \ F(this, "this") \
F(throw_iterator_result_not_an_object, "ThrowIteratorResultNotAnObject") \ F(throw_iterator_result_not_an_object, "ThrowIteratorResultNotAnObject") \
F(to_string, "ToString") \
F(use_asm, "use asm") \ F(use_asm, "use asm") \
F(use_strong, "use strong") \ F(use_strong, "use strong") \
F(use_strict, "use strict") \ F(use_strict, "use strict") \
......
...@@ -5476,27 +5476,24 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, ...@@ -5476,27 +5476,24 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
if (!tag) { if (!tag) {
// Build tree of BinaryOps to simplify code-generation // Build tree of BinaryOps to simplify code-generation
Expression* expr = NULL; Expression* expr = cooked_strings->at(0);
int i = 0;
while (i < expressions->length()) {
Expression* sub = expressions->at(i++);
Expression* cooked_str = cooked_strings->at(i);
// Let middle be ToString(sub).
ZoneList<Expression*>* args =
new (zone()) ZoneList<Expression*>(1, zone());
args->Add(sub, zone());
Expression* middle = factory()->NewCallRuntime(
ast_value_factory()->to_string_string(), NULL, args,
sub->position());
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( expr = factory()->NewBinaryOperation(
Token::ADD, expr, factory()->NewBinaryOperation( Token::ADD, factory()->NewBinaryOperation(
Token::ADD, cooked_str, expressions->at(i), Token::ADD, expr, middle, expr->position()),
cooked_str->position()), cooked_str, sub->position());
cooked_str->position());
}
cooked_str = cooked_strings->at(i);
expr = factory()->NewBinaryOperation(Token::ADD, expr, cooked_str,
cooked_str->position());
} }
return expr; return expr;
} else { } else {
......
...@@ -254,3 +254,39 @@ ...@@ -254,3 +254,39 @@
assertEquals("12345", String.raw(callSiteObj, arg(2), arg(4), arg(6))); assertEquals("12345", String.raw(callSiteObj, arg(2), arg(4), arg(6)));
assertEquals(["length", "raw1", "arg2", "raw3", "arg4", "raw5"], order); assertEquals(["length", "raw1", "arg2", "raw3", "arg4", "raw5"], order);
})(); })();
(function testStringRawToStringSubstitutionsOrder() {
var subs = [];
var log = [];
function stringify(toString) {
var valueOf = "_" + toString + "_";
return {
toString: function() { return toString; },
valueOf: function() { return valueOf; }
};
}
function getter(name, value) {
return {
get: function() {
log.push("get" + name);
return value;
},
set: function(v) {
log.push("set" + name);
}
};
}
Object.defineProperties(subs, {
0: getter(0, stringify("a")),
1: getter(1, stringify("b")),
2: getter(2, stringify("c"))
});
assertEquals("-a-b-c-", String.raw`-${subs[0]}-${subs[1]}-${subs[2]}-`);
assertArrayEquals(["get0", "get1", "get2"], log);
log.length = 0;
assertEquals("-a-", String.raw`-${subs[0]}-`);
assertArrayEquals(["get0"], log);
})();
...@@ -586,3 +586,96 @@ var global = this; ...@@ -586,3 +586,96 @@ var global = this;
"raw;test3" "raw;test3"
], raw); ], raw);
})(); })();
(function testToStringSubstitutions() {
var a = {
toString: function() { return "a"; },
valueOf: function() { return "-a-"; }
};
var b = {
toString: function() { return "b"; },
valueOf: function() { return "-b-"; }
};
assertEquals("a", `${a}`);
assertEquals("ab", `${a}${b}`);
assertEquals("-a--b-", `${a + b}`);
assertEquals("-a-", `${a + ""}`);
assertEquals("1a", `1${a}`);
assertEquals("1a2", `1${a}2`);
assertEquals("1a2b", `1${a}2${b}`);
assertEquals("1a2b3", `1${a}2${b}3`);
})();
(function testToStringSubstitutionsOrder() {
var subs = [];
var log = [];
function getter(name, value) {
return {
get: function() {
log.push("get" + name);
return value;
},
set: function(v) {
log.push("set" + name);
}
};
}
Object.defineProperties(subs, {
0: getter(0, "a"),
1: getter(1, "b"),
2: getter(2, "c")
});
assertEquals("-a-b-c-", `-${subs[0]}-${subs[1]}-${subs[2]}-`);
assertArrayEquals(["get0", "get1", "get2"], log);
})();
(function testTaggedToStringSubstitutionsOrder() {
var subs = [];
var log = [];
var tagged = [];
function getter(name, value) {
return {
get: function() {
log.push("get" + name);
return value;
},
set: function(v) {
log.push("set" + name);
}
};
}
Object.defineProperties(subs, {
0: getter(0, 1),
1: getter(1, 2),
2: getter(2, 3)
});
function tag(cs) {
var n_substitutions = arguments.length - 1;
var n_cooked = cs.length;
var e = cs[0];
var i = 0;
assertEquals(n_cooked, n_substitutions + 1);
while (i < n_substitutions) {
var sub = arguments[i++ + 1];
var tail = cs[i];
tagged.push(sub);
e = e.concat(sub, tail);
}
return e;
}
assertEquals("-1-2-3-", tag`-${subs[0]}-${subs[1]}-${subs[2]}-`);
assertArrayEquals(["get0", "get1", "get2"], log);
assertArrayEquals([1, 2, 3], tagged);
tagged.length = 0;
log.length = 0;
assertEquals("-1-", tag`-${subs[0]}-`);
assertArrayEquals(["get0"], log);
assertArrayEquals([1], tagged);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment