Skip to content

Tagged template literals compiled incorrectly, TemplateStringsArray not cached #17956

Closed
@justinfagnani

Description

@justinfagnani

TypeScript Version: 2.4.1

Code

let previousStrings;

function test(strings, ...value) {
  if (previousStrings !== undefined && previousStrings !== strings) {
    window.alert('failure');
  }
  previousStrings = strings;
}

function go(n) {
  return test`literal ${n}`;
}

Expected behavior:

According to the ECMAScript spec, every time a template tag is evaluated, the same strings object should be passed as the first argument:

Each TemplateLiteral in the program code of a realm is associated with a unique template object that is used in the evaluation of tagged Templates (12.2.9.6). The template objects are frozen and the same template object is used each time a specific tagged Template is evaluated.

https://tc39.github.io/ecma262/#sec-gettemplateobject

Actual behavior:

The above snippet compiles to:

var previousStrings;
function test(strings) {
    var value = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        value[_i - 1] = arguments[_i];
    }
    if (previousStrings !== undefined && previousStrings !== strings) {
        window.alert('failure');
    }
    previousStrings = strings;
}
function go(n) {
    return (_a = ["literal ", ""], _a.raw = ["literal ", ""], test(_a, n));
    var _a;
}

You can see that _a is going to have a new identity for each call of go().

FWIW, Babel compiles this correctly:

'use strict';

var _templateObject = _taggedTemplateLiteral(['literal ', ''], ['literal ', '']);

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

var previousStrings = void 0;

function test(strings) {
  if (previousStrings !== undefined && previousStrings !== strings) {
    window.alert('failure');
  }
  previousStrings = strings;
}

function go(n) {
  return test(_templateObject, n);
}

This is breaking lit-html when used in TypeScript: lit/lit#58

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptES6Relates to the ES6 SpecFixedA PR has been merged for this issue

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions