@@ -279,6 +279,16 @@ namespace ts {
279
279
let currentSourceFile : SourceFile ;
280
280
let currentText : string ;
281
281
let hierarchyFacts : HierarchyFacts ;
282
+ let taggedTemplateStringDeclarations : VariableDeclaration [ ] ;
283
+ function recordTaggedTemplateString ( temp : Identifier ) {
284
+ const decl = createVariableDeclaration ( temp ) ;
285
+ if ( ! taggedTemplateStringDeclarations ) {
286
+ taggedTemplateStringDeclarations = [ decl ] ;
287
+ }
288
+ else {
289
+ taggedTemplateStringDeclarations . push ( decl ) ;
290
+ }
291
+ }
282
292
283
293
/**
284
294
* Used to track if we are emitting body of the converted loop
@@ -307,6 +317,7 @@ namespace ts {
307
317
308
318
currentSourceFile = undefined ;
309
319
currentText = undefined ;
320
+ taggedTemplateStringDeclarations = undefined ;
310
321
hierarchyFacts = HierarchyFacts . None ;
311
322
return visited ;
312
323
}
@@ -520,6 +531,11 @@ namespace ts {
520
531
addCaptureThisForNodeIfNeeded ( statements , node ) ;
521
532
statementOffset = addCustomPrologue ( statements , node . statements , statementOffset , visitor ) ;
522
533
addRange ( statements , visitNodes ( node . statements , visitor , isStatement , statementOffset ) ) ;
534
+ if ( taggedTemplateStringDeclarations ) {
535
+ statements . push (
536
+ createVariableStatement ( /*modifiers*/ undefined ,
537
+ createVariableDeclarationList ( taggedTemplateStringDeclarations ) ) ) ;
538
+ }
523
539
addRange ( statements , endLexicalEnvironment ( ) ) ;
524
540
exitSubtree ( ancestorFacts , HierarchyFacts . None , HierarchyFacts . None ) ;
525
541
return updateSourceFileNode (
@@ -3637,10 +3653,12 @@ namespace ts {
3637
3653
const tag = visitNode ( node . tag , visitor , isExpression ) ;
3638
3654
3639
3655
// Allocate storage for the template site object
3640
- const temp = createTempVariable ( hoistVariableDeclaration ) ;
3656
+ const temp = createTempVariable ( recordTaggedTemplateString ) ;
3641
3657
3642
3658
// Build up the template arguments and the raw and cooked strings for the template.
3643
- const templateArguments : Expression [ ] = [ temp ] ;
3659
+ // We start out with 'undefined' for the first argument and revisit later
3660
+ // to avoid walking over the template string twice and shifting all our arguments over after the fact.
3661
+ const templateArguments : Expression [ ] = [ undefined ] ;
3644
3662
const cookedStrings : Expression [ ] = [ ] ;
3645
3663
const rawStrings : Expression [ ] = [ ] ;
3646
3664
const template = node . template ;
@@ -3658,16 +3676,14 @@ namespace ts {
3658
3676
}
3659
3677
}
3660
3678
3661
- // NOTE: The parentheses here is entirely optional as we are now able to auto-
3662
- // parenthesize when rebuilding the tree. This should be removed in a
3663
- // future version. It is here for now to match our existing emit.
3664
- return createParen (
3665
- inlineExpressions ( [
3666
- createAssignment ( temp , createArrayLiteral ( cookedStrings ) ) ,
3667
- createAssignment ( createPropertyAccess ( temp , "raw" ) , createArrayLiteral ( rawStrings ) ) ,
3668
- createCall ( tag , /*typeArguments*/ undefined , templateArguments )
3669
- ] )
3670
- ) ;
3679
+ // Initialize the template object if necessary
3680
+ templateArguments [ 0 ] = createLogicalOr (
3681
+ temp ,
3682
+ createAssignment (
3683
+ temp ,
3684
+ createTemplateObjectHelper ( context , createArrayLiteral ( cookedStrings ) , createArrayLiteral ( rawStrings ) ) ) )
3685
+
3686
+ return createCall ( tag , /*typeArguments*/ undefined , templateArguments ) ;
3671
3687
}
3672
3688
3673
3689
/**
@@ -4036,6 +4052,18 @@ namespace ts {
4036
4052
) ;
4037
4053
}
4038
4054
4055
+ function createTemplateObjectHelper ( context : TransformationContext , cooked : ArrayLiteralExpression , raw : ArrayLiteralExpression ) {
4056
+ context . requestEmitHelper ( templateObjectHelper ) ;
4057
+ return createCall (
4058
+ getHelperName ( "__getTemplateObject" ) ,
4059
+ /*typeArguments*/ undefined ,
4060
+ [
4061
+ cooked ,
4062
+ raw
4063
+ ]
4064
+ ) ;
4065
+ }
4066
+
4039
4067
const extendsHelper : EmitHelper = {
4040
4068
name : "typescript:extends" ,
4041
4069
scoped : false ,
@@ -4052,4 +4080,19 @@ namespace ts {
4052
4080
};
4053
4081
})();`
4054
4082
} ;
4083
+
4084
+ const templateObjectHelper : EmitHelper = {
4085
+ name : "typescript:getTemplateObject" ,
4086
+ scoped : false ,
4087
+ priority : 0 ,
4088
+ text : `
4089
+ var __getTemplateObject = (this && this.__getTemplateObject) || function (cooked, raw) {
4090
+ if (Object.freeze && Object.defineProperty) {
4091
+ return Object.freeze(Object.defineProperty(cooked, "raw", { value: Object.freeze(raw) }));
4092
+ }
4093
+ cooked.raw = raw;
4094
+ return cooked;
4095
+ };`
4096
+ } ;
4097
+
4055
4098
}
0 commit comments