@@ -2072,7 +2072,7 @@ module ts {
2072
2072
}
2073
2073
}
2074
2074
2075
- function emitParenthesized ( node : Node , parenthesized : boolean ) {
2075
+ function emitParenthesizedIf ( node : Node , parenthesized : boolean ) {
2076
2076
if ( parenthesized ) {
2077
2077
write ( "(" ) ;
2078
2078
}
@@ -2205,6 +2205,72 @@ module ts {
2205
2205
function getTemplateLiteralAsStringLiteral ( node : LiteralExpression ) : string {
2206
2206
return '"' + escapeString ( node . text ) + '"' ;
2207
2207
}
2208
+
2209
+ function emitDownlevelRawTemplateLiteral ( node : LiteralExpression ) {
2210
+ // Find original source text, since we need to emit the raw strings of the tagged template.
2211
+ // The raw strings contain the (escaped) strings of what the user wrote.
2212
+ // Examples: `\n` is converted to "\\n", a template string with a newline to "\n".
2213
+ var text = getSourceTextOfNodeFromSourceFile ( currentSourceFile , node ) ;
2214
+
2215
+ // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
2216
+ // thus we need to remove those characters.
2217
+ // First template piece starts with "`", others with " }"
2218
+ // Last template piece ends with "`", others with "${"
2219
+ var isLast = node . kind === SyntaxKind . NoSubstitutionTemplateLiteral || node . kind === SyntaxKind . TemplateTail ;
2220
+ text = text . substring ( 1 , text . length - ( isLast ? 1 : 2 ) ) ;
2221
+
2222
+ // Newline normalization:
2223
+ // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's
2224
+ // <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for both TV and TRV.
2225
+ text = text . replace ( / \r \n ? / g, "\n" ) ;
2226
+ text = escapeString ( text ) ;
2227
+
2228
+ write ( '"' + text + '"' ) ;
2229
+ }
2230
+
2231
+ function emitDownlevelTaggedTemplateArray ( node : TaggedTemplateExpression , literalEmitter : ( literal : LiteralExpression ) => void ) {
2232
+ write ( "[" ) ;
2233
+ if ( node . template . kind === SyntaxKind . NoSubstitutionTemplateLiteral ) {
2234
+ literalEmitter ( < LiteralExpression > node . template ) ;
2235
+ }
2236
+ else {
2237
+ literalEmitter ( ( < TemplateExpression > node . template ) . head ) ;
2238
+ forEach ( ( < TemplateExpression > node . template ) . templateSpans , ( child ) => {
2239
+ write ( ", " ) ;
2240
+ literalEmitter ( child . literal ) ;
2241
+ } ) ;
2242
+ }
2243
+ write ( "]" ) ;
2244
+ }
2245
+
2246
+ function emitDownlevelTaggedTemplate ( node : TaggedTemplateExpression ) {
2247
+ var tempVariable = createAndRecordTempVariable ( node ) ;
2248
+ write ( "(" ) ;
2249
+ emit ( tempVariable ) ;
2250
+ write ( " = " ) ;
2251
+ emitDownlevelTaggedTemplateArray ( node , emit ) ;
2252
+ write ( ", " ) ;
2253
+
2254
+ emit ( tempVariable ) ;
2255
+ write ( ".raw = " ) ;
2256
+ emitDownlevelTaggedTemplateArray ( node , emitDownlevelRawTemplateLiteral ) ;
2257
+ write ( ", " ) ;
2258
+
2259
+ emitParenthesizedIf ( node . tag , needsParenthesisForPropertyAccessOrInvocation ( node . tag ) ) ;
2260
+ write ( "(" ) ;
2261
+ emit ( tempVariable ) ;
2262
+
2263
+ // Now we emit the expressions
2264
+ if ( node . template . kind === SyntaxKind . TemplateExpression ) {
2265
+ forEach ( ( < TemplateExpression > node . template ) . templateSpans , templateSpan => {
2266
+ write ( ", " ) ;
2267
+ var needsParens = templateSpan . expression . kind === SyntaxKind . BinaryExpression
2268
+ && ( < BinaryExpression > templateSpan . expression ) . operatorToken . kind === SyntaxKind . CommaToken ;
2269
+ emitParenthesizedIf ( templateSpan . expression , needsParens ) ;
2270
+ } ) ;
2271
+ }
2272
+ write ( "))" ) ;
2273
+ }
2208
2274
2209
2275
function emitTemplateExpression ( node : TemplateExpression ) : void {
2210
2276
// In ES6 mode and above, we can simply emit each portion of a template in order, but in
@@ -2249,7 +2315,8 @@ module ts {
2249
2315
write ( " + " ) ;
2250
2316
}
2251
2317
2252
- emitParenthesized ( templateSpan . expression , needsParens ) ;
2318
+ emitParenthesizedIf ( templateSpan . expression , needsParens ) ;
2319
+
2253
2320
// Only emit if the literal is non-empty.
2254
2321
// The binary '+' operator is left-associative, so the first string concatenation
2255
2322
// with the head will force the result up to this point to be a string.
@@ -2479,7 +2546,7 @@ module ts {
2479
2546
emit ( ( < SpreadElementExpression > node ) . expression ) ;
2480
2547
}
2481
2548
2482
- function needsParenthesisForPropertyAccess ( node : Expression ) {
2549
+ function needsParenthesisForPropertyAccessOrInvocation ( node : Expression ) {
2483
2550
switch ( node . kind ) {
2484
2551
case SyntaxKind . Identifier :
2485
2552
case SyntaxKind . ArrayLiteralExpression :
@@ -2509,7 +2576,7 @@ module ts {
2509
2576
var e = elements [ pos ] ;
2510
2577
if ( e . kind === SyntaxKind . SpreadElementExpression ) {
2511
2578
e = ( < SpreadElementExpression > e ) . expression ;
2512
- emitParenthesized ( e , /*parenthesized*/ group === 0 && needsParenthesisForPropertyAccess ( e ) ) ;
2579
+ emitParenthesizedIf ( e , /*parenthesized*/ group === 0 && needsParenthesisForPropertyAccessOrInvocation ( e ) ) ;
2513
2580
pos ++ ;
2514
2581
}
2515
2582
else {
@@ -2985,9 +3052,14 @@ module ts {
2985
3052
}
2986
3053
2987
3054
function emitTaggedTemplateExpression ( node : TaggedTemplateExpression ) : void {
2988
- emit ( node . tag ) ;
2989
- write ( " " ) ;
2990
- emit ( node . template ) ;
3055
+ if ( compilerOptions . target >= ScriptTarget . ES6 ) {
3056
+ emit ( node . tag ) ;
3057
+ write ( " " ) ;
3058
+ emit ( node . template ) ;
3059
+ }
3060
+ else {
3061
+ emitDownlevelTaggedTemplate ( node ) ;
3062
+ }
2991
3063
}
2992
3064
2993
3065
function emitParenExpression ( node : ParenthesizedExpression ) {
@@ -3157,7 +3229,7 @@ module ts {
3157
3229
}
3158
3230
3159
3231
function emitExpressionStatement ( node : ExpressionStatement ) {
3160
- emitParenthesized ( node . expression , /*parenthesized*/ node . expression . kind === SyntaxKind . ArrowFunction ) ;
3232
+ emitParenthesizedIf ( node . expression , /*parenthesized*/ node . expression . kind === SyntaxKind . ArrowFunction ) ;
3161
3233
write ( ";" ) ;
3162
3234
}
3163
3235
0 commit comments