[CS2] Fix #4629: interpolations (whether in strings or CSX tags) with only comments (#4659)

* Fix #4629: interpolations (whether in strings or CSX tags) that contain nothing but comments should not be optimized out

* Template literals need an expression inside their interpolations, so if we only have a comment to put in there, toss in an empty string as well
This commit is contained in:
Geoffrey Booth 2017-08-23 23:34:59 -07:00 committed by GitHub
parent a3b08e1bef
commit 40c351135a
3 changed files with 65 additions and 6 deletions

View File

@ -1089,7 +1089,7 @@
// of `'NEOSTRING'`s are converted using `fn` and turned into strings using
// `options` first.
mergeInterpolationTokens(tokens, options, fn) {
var converted, firstEmptyStringIndex, firstIndex, i, j, lastToken, len, locationToken, lparen, plusToken, rparen, tag, token, tokensToPush, value;
var converted, firstEmptyStringIndex, firstIndex, i, j, k, lastToken, len, len1, locationToken, lparen, placeholderToken, plusToken, rparen, tag, token, tokensToPush, val, value;
if (tokens.length > 1) {
lparen = this.token('STRING_START', '(', 0, 0);
}
@ -1100,8 +1100,32 @@
switch (tag) {
case 'TOKENS':
if (value.length === 2) {
// Optimize out empty interpolations (an empty pair of parentheses).
continue;
if (!(value[0].comments || value[1].comments)) {
// Optimize out empty interpolations (an empty pair of parentheses).
continue;
}
// There are comments (and nothing else) in this interpolation.
if (this.csxDepth === 0) {
// This is an interpolated string, not a CSX tag; and for whatever
// reason `` `a${/*test*/}b` `` is invalid JS. So compile to
// `` `a${/*test*/''}b` `` instead.
placeholderToken = this.makeToken('STRING', "''");
} else {
placeholderToken = this.makeToken('JS', '');
}
// Use the same location data as the first parenthesis.
placeholderToken[2] = value[0][2];
for (k = 0, len1 = value.length; k < len1; k++) {
val = value[k];
if (!val.comments) {
continue;
}
if (placeholderToken.comments == null) {
placeholderToken.comments = [];
}
placeholderToken.comments.push(...val.comments);
}
value.splice(1, 0, placeholderToken);
}
// Push all the tokens in the fake `'TOKENS'` token. These already have
// sane location data.

View File

@ -139,7 +139,7 @@ exports.Lexer = class Lexer
return id.length
if id is 'do' and regExSuper = /^(\s*super)(?!\(\))/.exec @chunk[3...]
@token 'SUPER', 'super'
@token 'CALL_START', '('
@token 'CALL_START', '('
@token 'CALL_END', ')'
[input, sup] = regExSuper
return sup.length + 3
@ -820,8 +820,23 @@ exports.Lexer = class Lexer
[tag, value] = token
switch tag
when 'TOKENS'
# Optimize out empty interpolations (an empty pair of parentheses).
continue if value.length is 2
if value.length is 2
# Optimize out empty interpolations (an empty pair of parentheses).
continue unless value[0].comments or value[1].comments
# There are comments (and nothing else) in this interpolation.
if @csxDepth is 0
# This is an interpolated string, not a CSX tag; and for whatever
# reason `` `a${/*test*/}b` `` is invalid JS. So compile to
# `` `a${/*test*/''}b` `` instead.
placeholderToken = @makeToken 'STRING', "''"
else
placeholderToken = @makeToken 'JS', ''
# Use the same location data as the first parenthesis.
placeholderToken[2] = value[0][2]
for val in value when val.comments
placeholderToken.comments ?= []
placeholderToken.comments.push val.comments...
value.splice 1, 0, placeholderToken
# Push all the tokens in the fake `'TOKENS'` token. These already have
# sane location data.
locationToken = value[0]

View File

@ -721,6 +721,26 @@ test "Empty lines between comments are preserved", ->
3;
}'''
test "Block comment in an interpolated string", ->
eqJS '"a#{### Comment ###}b"', "`a${/* Comment */''}b`;"
eqJS '"a#{### 1 ###}b#{### 2 ###}c"', "`a${/* 1 */''}b${/* 2 */''}c`;"
test "#4629: Block comment in CSX interpolation", ->
eqJS '<div>{### Comment ###}</div>', '<div>{/* Comment */}</div>;'
eqJS '''
<div>
{###
Multiline
Comment
###}
</div>''', '''
<div>
{/*
Multiline
Comment
*/}
</div>;'''
test "Line comment in an interpolated string", ->
eqJS '''
"a#{# Comment