Merge pull request #4383 from GeoffreyBooth/escape-template-literals

Escape backticks and `${` within template literals; fixes #4380
This commit is contained in:
Simon Lydell
2016-12-03 20:41:25 +01:00
committed by GitHub
3 changed files with 50 additions and 3 deletions

View File

@@ -3351,7 +3351,7 @@
}
StringWithInterpolations.prototype.compileNode = function(o) {
var element, elements, expr, fragments, j, len1;
var element, elements, expr, fragments, j, len1, value;
if (!o.inTaggedTemplateCall) {
return StringWithInterpolations.__super__.compileNode.apply(this, arguments);
}
@@ -3372,7 +3372,15 @@
for (j = 0, len1 = elements.length; j < len1; j++) {
element = elements[j];
if (element instanceof StringLiteral) {
fragments.push(this.makeCode(element.value.slice(1, -1)));
value = element.value.slice(1, -1);
value = value.replace(/(\\*)(`|\$\{)/g, function(match, backslashes, toBeEscaped) {
if (backslashes.length % 2 === 0) {
return backslashes + "\\" + toBeEscaped;
} else {
return match;
}
});
fragments.push(this.makeCode(value));
} else {
fragments.push(this.makeCode('${'));
fragments.push.apply(fragments, element.compileToFragments(o, LEVEL_PAREN));

View File

@@ -2274,7 +2274,14 @@ exports.StringWithInterpolations = class StringWithInterpolations extends Parens
fragments.push @makeCode '`'
for element in elements
if element instanceof StringLiteral
fragments.push @makeCode element.value.slice(1, -1)
value = element.value[1...-1]
# Backticks and `${` inside template literals must be escaped.
value = value.replace /(\\*)(`|\$\{)/g, (match, backslashes, toBeEscaped) ->
if backslashes.length % 2 is 0
"#{backslashes}\\#{toBeEscaped}"
else
match
fragments.push @makeCode value
else
fragments.push @makeCode '${'
fragments.push element.compileToFragments(o, LEVEL_PAREN)...

View File

@@ -137,3 +137,35 @@ test "tagged template literal with an interpolated string that itself contains a
test "tagged template literal with an interpolated string that contains a tagged template literal", ->
eq 'text: [inner tagged | literal] expressions: [text: [|] expressions: [template]]',
func"inner tagged #{func"#{'template'}"} literal"
test "tagged template literal with backticks", ->
eq 'text: [ES template literals look like this: `foo bar`] expressions: []',
func"ES template literals look like this: `foo bar`"
test "tagged template literal with escaped backticks", ->
eq 'text: [ES template literals look like this: \\`foo bar\\`] expressions: []',
func"ES template literals look like this: \\`foo bar\\`"
test "tagged template literal with unnecessarily escaped backticks", ->
eq 'text: [ES template literals look like this: `foo bar`] expressions: []',
func"ES template literals look like this: \`foo bar\`"
test "tagged template literal with ES interpolation", ->
eq 'text: [ES template literals also look like this: `3 + 5 = ${3+5}`] expressions: []',
func"ES template literals also look like this: `3 + 5 = ${3+5}`"
test "tagged template literal with both ES and CoffeeScript interpolation", ->
eq "text: [ES template literals also look like this: `3 + 5 = ${3+5}` which equals |] expressions: [8]",
func"ES template literals also look like this: `3 + 5 = ${3+5}` which equals #{3+5}"
test "tagged template literal with escaped ES interpolation", ->
eq 'text: [ES template literals also look like this: `3 + 5 = \\${3+5}`] expressions: []',
func"ES template literals also look like this: `3 + 5 = \\${3+5}`"
test "tagged template literal with unnecessarily escaped ES interpolation", ->
eq 'text: [ES template literals also look like this: `3 + 5 = ${3+5}`] expressions: []',
func"ES template literals also look like this: `3 + 5 = \${3+5}`"
test "tagged template literal special escaping", ->
eq 'text: [` ` \\` \\` \\\\` $ { ${ ${ \\${ \\${ \\\\${ | ` ${] expressions: [1]',
func"` \` \\` \\\` \\\\` $ { ${ \${ \\${ \\\${ \\\\${ #{1} ` ${"