Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Template Literal Flags are confused for ContainsInvalidEscape causing tagged template expressions to be unnecessarily transpiled #55369

Closed
engelsdamien opened this issue Aug 14, 2023 · 0 comments · Fixed by #55373

Comments

@engelsdamien
Copy link
Contributor

🔎 Search Terms

In processTaggedTemplateExpression the code checks whether the tagged template expression using the hasInvalidEscape function. This was done in #12700 to support a new feature in tagged template literals allowing for invalid escape sequences.

Unfortunately, the function was written in a way that relies on implicit from number -> boolean instead of masking the templateFlags field:

/** @internal */
export function hasInvalidEscape(template: TemplateLiteral): boolean {
    return template && !!(isNoSubstitutionTemplateLiteral(template)
        ? template.templateFlags
        : (template.head.templateFlags || some(template.templateSpans, span => !!span.literal.templateFlags)));
}

This means the code assumes any template literal with non-zero flags contains an invalid escape. While this was true in the past, new flags were introduced in 5.1 breaking the logic of the code.

Now all tagged templates containing unicode escape sequences now get transpiled when they don't need to, causing a code size increase.

🕗 Version & Regression Information

This changed between versions 5.0.4 and 5.1.6

v5.0.4: https://www.typescriptlang.org/play?target=3&jsx=0&module=1&ts=5.0.4#code/GYVwdgxgLglg9mABMOcA8AVAfACgIYBciGAlAN4BOAplCBUngNwC+AUBAgM5SJ6IC8yVAAMAOiAAMUicMbsuPAEYChcYXllA

v5.1.6: https://www.typescriptlang.org/play?target=3&jsx=0&module=1&ts=5.1.6#code/GYVwdgxgLglg9mABMOcA8AVAfACgIYBciGAlAN4BOAplCBUngNwC+AUBAgM5SJ6IC8yVAAMAOiAAMUicMbsuPAEYChcYXllA

⏯ Playground Link

https://www.typescriptlang.org/play?target=3&jsx=0&module=1&ts=5.1.6#code/GYVwdgxgLglg9mABMOcA8AVAfACgIYBciGAlAN4BOAplCBUngNwC+AUBAgM5SJ6IC8yVAAMAOiAAMUicMbsuPAEYChcYXllA

💻 Code

function foo<T>(a: T){return a;}
const a = foo`\u0000`;
const b = foo`a`;

🙁 Actual behavior

"use strict";
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
    if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
    return cooked;
};
function foo(a) { return a; }
const a = foo(__makeTemplateObject(["\0"], ["\\u0000"]));
const b = foo `a`;

🙂 Expected behavior

"use strict";
function foo(a) { return a; }
const a = foo `\u0000`;
const b = foo `a`;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant