mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Update emit for tagged templates to use a per-site cached template objects.
This commit is contained in:
@@ -16587,6 +16587,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type {
|
||||
if (languageVersion < ScriptTarget.ES2015) {
|
||||
checkExternalEmitHelpers(node, ExternalEmitHelpers.GetTemplateObject);
|
||||
}
|
||||
return getReturnTypeOfSignature(getResolvedSignature(node));
|
||||
}
|
||||
|
||||
@@ -23919,6 +23922,7 @@ namespace ts {
|
||||
case ExternalEmitHelpers.AsyncDelegator: return "__asyncDelegator";
|
||||
case ExternalEmitHelpers.AsyncValues: return "__asyncValues";
|
||||
case ExternalEmitHelpers.ExportStar: return "__exportStar";
|
||||
case ExternalEmitHelpers.GetTemplateObject: return "__getTemplateObject";
|
||||
default: Debug.fail("Unrecognized helper");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,6 +279,16 @@ namespace ts {
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentText: string;
|
||||
let hierarchyFacts: HierarchyFacts;
|
||||
let taggedTemplateStringDeclarations: VariableDeclaration[];
|
||||
function recordTaggedTemplateString(temp: Identifier) {
|
||||
const decl = createVariableDeclaration(temp);
|
||||
if (!taggedTemplateStringDeclarations) {
|
||||
taggedTemplateStringDeclarations = [decl];
|
||||
}
|
||||
else {
|
||||
taggedTemplateStringDeclarations.push(decl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to track if we are emitting body of the converted loop
|
||||
@@ -307,6 +317,7 @@ namespace ts {
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentText = undefined;
|
||||
taggedTemplateStringDeclarations = undefined;
|
||||
hierarchyFacts = HierarchyFacts.None;
|
||||
return visited;
|
||||
}
|
||||
@@ -520,6 +531,11 @@ namespace ts {
|
||||
addCaptureThisForNodeIfNeeded(statements, node);
|
||||
statementOffset = addCustomPrologue(statements, node.statements, statementOffset, visitor);
|
||||
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
|
||||
if (taggedTemplateStringDeclarations) {
|
||||
statements.push(
|
||||
createVariableStatement(/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(taggedTemplateStringDeclarations)));
|
||||
}
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
return updateSourceFileNode(
|
||||
@@ -3637,10 +3653,12 @@ namespace ts {
|
||||
const tag = visitNode(node.tag, visitor, isExpression);
|
||||
|
||||
// Allocate storage for the template site object
|
||||
const temp = createTempVariable(hoistVariableDeclaration);
|
||||
const temp = createTempVariable(recordTaggedTemplateString);
|
||||
|
||||
// Build up the template arguments and the raw and cooked strings for the template.
|
||||
const templateArguments: Expression[] = [temp];
|
||||
// We start out with 'undefined' for the first argument and revisit later
|
||||
// to avoid walking over the template string twice and shifting all our arguments over after the fact.
|
||||
const templateArguments: Expression[] = [undefined];
|
||||
const cookedStrings: Expression[] = [];
|
||||
const rawStrings: Expression[] = [];
|
||||
const template = node.template;
|
||||
@@ -3658,16 +3676,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: The parentheses here is entirely optional as we are now able to auto-
|
||||
// parenthesize when rebuilding the tree. This should be removed in a
|
||||
// future version. It is here for now to match our existing emit.
|
||||
return createParen(
|
||||
inlineExpressions([
|
||||
createAssignment(temp, createArrayLiteral(cookedStrings)),
|
||||
createAssignment(createPropertyAccess(temp, "raw"), createArrayLiteral(rawStrings)),
|
||||
createCall(tag, /*typeArguments*/ undefined, templateArguments)
|
||||
])
|
||||
);
|
||||
// Initialize the template object if necessary
|
||||
templateArguments[0] = createLogicalOr(
|
||||
temp,
|
||||
createAssignment(
|
||||
temp,
|
||||
createTemplateObjectHelper(context, createArrayLiteral(cookedStrings), createArrayLiteral(rawStrings))));
|
||||
|
||||
return createCall(tag, /*typeArguments*/ undefined, templateArguments);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4036,6 +4052,18 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
function createTemplateObjectHelper(context: TransformationContext, cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression) {
|
||||
context.requestEmitHelper(templateObjectHelper);
|
||||
return createCall(
|
||||
getHelperName("__getTemplateObject"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
cooked,
|
||||
raw
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
const extendsHelper: EmitHelper = {
|
||||
name: "typescript:extends",
|
||||
scoped: false,
|
||||
@@ -4052,4 +4080,19 @@ namespace ts {
|
||||
};
|
||||
})();`
|
||||
};
|
||||
|
||||
const templateObjectHelper: EmitHelper = {
|
||||
name: "typescript:getTemplateObject",
|
||||
scoped: false,
|
||||
priority: 0,
|
||||
text: `
|
||||
var __getTemplateObject = (this && this.__getTemplateObject) || function (cooked, raw) {
|
||||
if (Object.freeze && Object.defineProperty) {
|
||||
return Object.freeze(Object.defineProperty(cooked, "raw", { value: Object.freeze(raw) }));
|
||||
}
|
||||
cooked.raw = raw;
|
||||
return cooked;
|
||||
};`
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4217,22 +4217,23 @@ namespace ts {
|
||||
*/
|
||||
/* @internal */
|
||||
export const enum ExternalEmitHelpers {
|
||||
Extends = 1 << 0, // __extends (used by the ES2015 class transformation)
|
||||
Assign = 1 << 1, // __assign (used by Jsx and ESNext object spread transformations)
|
||||
Rest = 1 << 2, // __rest (used by ESNext object rest transformation)
|
||||
Decorate = 1 << 3, // __decorate (used by TypeScript decorators transformation)
|
||||
Metadata = 1 << 4, // __metadata (used by TypeScript decorators transformation)
|
||||
Param = 1 << 5, // __param (used by TypeScript decorators transformation)
|
||||
Awaiter = 1 << 6, // __awaiter (used by ES2017 async functions transformation)
|
||||
Generator = 1 << 7, // __generator (used by ES2015 generator transformation)
|
||||
Values = 1 << 8, // __values (used by ES2015 for..of and yield* transformations)
|
||||
Read = 1 << 9, // __read (used by ES2015 iterator destructuring transformation)
|
||||
Spread = 1 << 10, // __spread (used by ES2015 array spread and argument list spread transformations)
|
||||
Await = 1 << 11, // __await (used by ES2017 async generator transformation)
|
||||
AsyncGenerator = 1 << 12, // __asyncGenerator (used by ES2017 async generator transformation)
|
||||
AsyncDelegator = 1 << 13, // __asyncDelegator (used by ES2017 async generator yield* transformation)
|
||||
AsyncValues = 1 << 14, // __asyncValues (used by ES2017 for..await..of transformation)
|
||||
ExportStar = 1 << 15, // __exportStar (used by CommonJS/AMD/UMD module transformation)
|
||||
Extends = 1 << 0, // __extends (used by the ES2015 class transformation)
|
||||
Assign = 1 << 1, // __assign (used by Jsx and ESNext object spread transformations)
|
||||
Rest = 1 << 2, // __rest (used by ESNext object rest transformation)
|
||||
Decorate = 1 << 3, // __decorate (used by TypeScript decorators transformation)
|
||||
Metadata = 1 << 4, // __metadata (used by TypeScript decorators transformation)
|
||||
Param = 1 << 5, // __param (used by TypeScript decorators transformation)
|
||||
Awaiter = 1 << 6, // __awaiter (used by ES2017 async functions transformation)
|
||||
Generator = 1 << 7, // __generator (used by ES2015 generator transformation)
|
||||
Values = 1 << 8, // __values (used by ES2015 for..of and yield* transformations)
|
||||
Read = 1 << 9, // __read (used by ES2015 iterator destructuring transformation)
|
||||
Spread = 1 << 10, // __spread (used by ES2015 array spread and argument list spread transformations)
|
||||
Await = 1 << 11, // __await (used by ES2017 async generator transformation)
|
||||
AsyncGenerator = 1 << 12, // __asyncGenerator (used by ES2017 async generator transformation)
|
||||
AsyncDelegator = 1 << 13, // __asyncDelegator (used by ES2017 async generator yield* transformation)
|
||||
AsyncValues = 1 << 14, // __asyncValues (used by ES2017 for..await..of transformation)
|
||||
ExportStar = 1 << 15, // __exportStar (used by CommonJS/AMD/UMD module transformation)
|
||||
GetTemplateObject = 1 << 16, // __getTemplateObject (used for constructing template string array objects)
|
||||
|
||||
// Helpers included by ES2015 for..of
|
||||
ForOfIncludes = Values,
|
||||
|
||||
Reference in New Issue
Block a user