function test(actual, expected) { if (actual !== expected) throw new Error("bad value: " + actual); } function testEval(script, expected) { test(eval(script), expected); } function testEmbedded(value, expected) { var template = `Hello ${value} World`; test(template, expected); } test(``, ""); test(`${""}`, ""); test(`${``}`, ""); test(`${``}${``}${``}${""}`, ""); test(`Hello World`, "Hello World"); test(`Hello World`, "Hello\n World"); test(`\uFEFF`, "\uFEFF"); testEval("`\uFEFF`", "\uFEFF"); test(`\x20`, "\x20"); test(`\x2020`, "\x2020"); for (var ch of [ '\'', '"', '\\', 'b', 'f', 'n', 'r', 't', 'v' ]) testEval("`\\" + ch + "`", eval("'\\" + ch + "'")); test(`\ Hello World`, "Hello World"); test(`\ Hello World`, "\nHello World"); test(`\u2028\u2029\r\n`, "\u2028\u2029\r\n"); test(`\u2028\u2029\n\r\n`, "\u2028\u2029\n\r\n"); test(`\u2028200`, "\u2028200"); testEmbedded(42, "Hello 42 World"); testEmbedded("ISUCA", "Hello ISUCA World"); testEmbedded(null, "Hello null World"); testEmbedded(undefined, "Hello undefined World"); testEmbedded({}, "Hello [object Object] World"); (function () { var object = { name: "Cocoa", }; var array = [ "Cappuccino" ] test(`Hello ${object.name} and ${array[0]} :D`, "Hello Cocoa and Cappuccino :D"); }()); (function () { function ok() { return "Cocoa"; } test(`Hello ${ ok() }`, "Hello Cocoa"); }()); (function () { var object = { toString() { return 'Cocoa'; } }; test(`Hello ${object} :D`, "Hello Cocoa :D"); }()); // Immediately adjacent template expressions, with empty intermediate template strings. test(`${"C"}${"o"}${"c"}${"o"}${"a"}`, "Cocoa"); test(`${"C"}${"o"}${"c"}${"o"}${" "}`, "Coco "); // Nested templates. test(`Hello ${ `Cocoa` }`, "Hello Cocoa"); test(`Hello ${ `Co${`c`}oa` }`, "Hello Cocoa"); // Evaluation order (function () { var count = 0; function check(num) { var now = count++; test(now, num); return now; } test(`Hello ${ `${ check(0) } ${ ` ${ check(1) } ${ check(2) }` } ${ check(3) }` } ${ check(4) }`, "Hello 0 1 2 3 4") }()); // Exceptions (function () { function gen(num) { return { toString() { throw new Error(num); } }; } var error = null; try { var template = `${gen(0)} ${gen(1)} ${gen(2)}`; } catch (e) { error = e; } if (!error) throw new Error('no error thrown'); if (String(error) !== 'Error: 0') throw new Error("bad error: " + String(error)); var error = null; try { var template = `${52} ${gen(0)} ${gen(1)}`; } catch (e) { error = e; } if (!error) throw new Error('no error thrown'); if (String(error) !== 'Error: 0') throw new Error("bad error: " + String(error)); }()); (function () { var stat= { count: 0 }; function gen(num) { stat[num] = { called: true, count: stat.count++, toString: null }; return { toString() { stat[num].toString = { called: true, count: stat.count++, }; throw new Error(num); } }; } var error = null; try { var template = `${gen(0)} ${gen(1)} ${gen(2)}`; } catch (e) { error = e; } if (!error) throw new Error('no error thrown'); if (String(error) !== 'Error: 0') throw new Error("bad error: " + String(error)); test(stat[0].count, 0); test(stat[0].toString.called, true); test(stat[0].toString.count, 1); test(stat[1], undefined); test(stat[2], undefined); }()); (function () { var stat= { count: 0 }; function gen(num) { stat[num] = { called: true, count: stat.count++, toString: null }; return { toString() { stat[num].toString = { called: true, count: stat.count++, }; throw new Error(num); } }; } var error = null; try { var template = `${ `${gen(0)}` } ${ `${gen(1)} ${gen(2)}` }`; } catch (e) { error = e; } if (!error) throw new Error('no error thrown'); if (String(error) !== 'Error: 0') throw new Error("bad error: " + String(error)); test(stat[0].count, 0); test(stat[0].toString.called, true); test(stat[0].toString.count, 1); test(stat[1], undefined); test(stat[2], undefined); }()); dfgTests =[ function testSingleNode() { for (var i = 0; i < 1000; i++) `${1}` }, function testPreNode() { for (var i = 0; i < 1000; i++) `n${1}` }, function testPostNode() { for (var i = 0; i < 1000; i++) `${1}n` }, function testSingleObjectNode() { for (var i = 0; i < 1000; i++) `${{}}` }, function testObjectPreNode() { for (var i = 0; i < 1000; i++) `n${{}}` }, function testObjectPostNode() { for (var i = 0; i < 1000; i++) `${{}}n` }, ]; for(var f of dfgTests) { noInline(f) f(); }