Cherry-pick PR #38500 into release-3.9

Component commits:
ee3f2ce362 regression(38485): allow using rawText property in processing a tagged template
This commit is contained in:
Alexander T 2020-05-12 17:42:46 +00:00 committed by typescript-bot
parent bd2833f5f8
commit f185491092
3 changed files with 36 additions and 8 deletions

View file

@ -71,18 +71,21 @@ namespace ts {
*
* @param node The ES6 template literal.
*/
function getRawLiteral(node: LiteralLikeNode, currentSourceFile: SourceFile) {
function getRawLiteral(node: TemplateLiteralLikeNode, currentSourceFile: SourceFile) {
// Find original source text, since we need to emit the raw strings of the tagged template.
// The raw strings contain the (escaped) strings of what the user wrote.
// Examples: `\n` is converted to "\\n", a template string with a newline to "\n".
let text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
let text = node.rawText;
if (text === undefined) {
text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
// text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
// thus we need to remove those characters.
// First template piece starts with "`", others with "}"
// Last template piece ends with "`", others with "${"
const isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail;
text = text.substring(1, text.length - (isLast ? 1 : 2));
// text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
// thus we need to remove those characters.
// First template piece starts with "`", others with "}"
// Last template piece ends with "`", others with "${"
const isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail;
text = text.substring(1, text.length - (isLast ? 1 : 2));
}
// Newline normalization:
// ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's

View file

@ -50,6 +50,15 @@ namespace ts {
return (node: SourceFile) => visitNode(node, visitor);
}
function createTaggedTemplateLiteral(): Transformer<SourceFile> {
return sourceFile => updateSourceFileNode(sourceFile, [
createStatement(
createTaggedTemplate(
createIdentifier("$tpl"),
createNoSubstitutionTemplateLiteral("foo", "foo")))
]);
}
function transformSourceFile(sourceText: string, transformers: TransformerFactory<SourceFile>[]) {
const transformed = transform(createSourceFile("source.ts", sourceText, ScriptTarget.ES2015), transformers);
const printer = createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed }, {
@ -120,6 +129,17 @@ namespace ts {
}).outputText;
});
testBaseline("transformTaggedTemplateLiteral", () => {
return transpileModule("", {
transformers: {
before: [createTaggedTemplateLiteral],
},
compilerOptions: {
target: ScriptTarget.ES5
}
}).outputText;
});
testBaseline("issue27854", () => {
return transpileModule(`oldName<{ a: string; }>\` ... \`;`, {
transformers: {

View file

@ -0,0 +1,5 @@
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};
$tpl(__makeTemplateObject(["foo"], ["foo"]));