template-literal.js   [plain text]



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);
}());