fix escape of $ in template strings

https://github.com/dart-lang/dev_compiler/issues/379

R=vsm@google.com

Review URL: https://codereview.chromium.org/1426243002 .
This commit is contained in:
John Messerly 2015-11-02 10:32:49 -08:00
parent edd9cbe7ea
commit 749d820ce6
6 changed files with 26 additions and 15 deletions

View file

@ -2375,10 +2375,10 @@ dart_library.library('dart/_internal', null, /* Imports */[
let POWERS_OF_TEN = dart.const([1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0, 100000000000000.0, 1000000000000000.0, 10000000000000000.0, 100000000000000000.0, 1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0, 1e+21, 1e+22]);
dart.defineLazyProperties(Symbol, {
get publicSymbolPattern() {
return core.RegExp.new(`^(?:${Symbol.operatorRE}$|${Symbol.publicIdentifierRE}(?:=?$|[.](?!$)))+?$`);
return core.RegExp.new(`^(?:${Symbol.operatorRE}\$|${Symbol.publicIdentifierRE}(?:=?\$|[.](?!\$)))+?\$`);
},
get symbolPattern() {
return core.RegExp.new(`^(?:${Symbol.operatorRE}$|${Symbol.identifierRE}(?:=?$|[.](?!$)))+?$`);
return core.RegExp.new(`^(?:${Symbol.operatorRE}\$|${Symbol.identifierRE}(?:=?\$|[.](?!\$)))+?\$`);
}
});
// Exports:

View file

@ -1184,7 +1184,7 @@ dart_library.library('dart/core', null, /* Imports */[
[_getKey]() {
let key = dart.as(_js_helper.Primitives.getProperty(this, Expando$()._KEY_PROPERTY_NAME), String);
if (key == null) {
key = `expando$key$${(() => {
key = `expando\$key\$${(() => {
let x = Expando$()._keyCount;
Expando$()._keyCount = dart.notNull(x) + 1;
return x;

View file

@ -299,28 +299,35 @@ class JsBuilder {
// Start by escaping the backslashes.
String escaped = value.replaceAll('\\', '\\\\');
// Replace $ in template strings:
// http://www.ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components
var quoteReplace = quote == '`' ? r'`$' : quote;
// http://www.ecma-international.org/ecma-262/6.0/#sec-literals-string-literals
// > All code points may appear literally in a string literal except for the
// > closing quote code points, U+005C (REVERSE SOLIDUS),
// > U+000D (CARRIAGE RETURN), U+2028 (LINE SEPARATOR),
// > U+2029 (PARAGRAPH SEPARATOR), and U+000A (LINE FEED).
var re = new RegExp('\n|\r|$quote|\b|\f|\t|\v|\u2028|\u2029');
var re = new RegExp('[\n\r$quoteReplace\b\f\t\v\u2028\u2029]');
escaped = escaped.replaceAllMapped(re, (m) {
switch (m.group(0)) {
case "\n" : return r"\n";
case "\r" : return r"\r";
case "\u2028": return r"\u2028";
case "\u2029": return r"\u2029";
// Quotes are only replaced if they conflict with the containing quote
case '"': return r'\"';
case "'": return r"\'";
case "`": return r"\`";
// Quotes and $ are only replaced if they conflict with the containing
// quote, see regex above.
case '"': return r'\"';
case "'": return r"\'";
case "`": return r"\`";
case r"$": return r"\$";
// TODO(jmesserly): these don't need to be escaped for correctness,
// but they are conventionally escaped.
case "\b" : return r"\b";
case "\t" : return r"\t";
case "\f" : return r"\f";
case "\v" : return r"\v";
case "\b": return r"\b";
case "\t": return r"\t";
case "\f": return r"\f";
case "\v": return r"\v";
}
});
LiteralString result = new LiteralString('$quote$escaped$quote');

View file

@ -9,12 +9,12 @@ author: Dart Dev Compiler team <dev-compiler@dartlang.org>
homepage: https://github.com/dart-lang/dev_compiler
dependencies:
analyzer: ^0.26.1+10
analyzer: ^0.26.1+17
args: ^0.13.0
cli_util: ^0.0.1
crypto: ^0.9.0
html: ^0.12.0
js: ^0.6.0-beta.6
js: ^0.6.0-beta.7
logging: ">=0.9.2 <0.12.0"
path: ^1.3.0
pub_semver: ^1.1.0

View file

@ -43,7 +43,8 @@ dart_library.library('misc', null, /* Imports */[
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
dart.fn(_isWhitespace, core.bool, [core.String]);
let _escapeMap = dart.const(dart.map({'\n': '\\n', '\r': '\\r', '\f': '\\f', '\b': '\\b', '\t': '\\t', '\v': '\\v', '': '\\x7F'}));
let expr = 'foo';
let _escapeMap = dart.const(dart.map({'\n': '\\n', '\r': '\\r', '\f': '\\f', '\b': '\\b', '\t': '\\t', '\v': '\\v', '': '\\x7F', [`\${${expr}}`]: ''}));
function main() {
core.print(dart.toString(1));
core.print(dart.toString(1.0));
@ -61,5 +62,6 @@ dart_library.library('misc', null, /* Imports */[
exports.Generic = Generic;
exports.Base = Base;
exports.Derived = Derived;
exports.expr = expr;
exports.main = main;
});

View file

@ -31,6 +31,7 @@ class Derived {
bool _isWhitespace(String ch) =>
ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
const expr = 'foo';
const _escapeMap = const {
'\n': r'\n',
'\r': r'\r',
@ -39,6 +40,7 @@ const _escapeMap = const {
'\t': r'\t',
'\v': r'\v',
'\x7F': r'\x7F', // delete
'\${${expr}}': ''
};