Print \x and \u escapes in strings and regexes lowercase (#522)
* Print \x and \u escapes in strings and regexes lowercase Theoretically, we would want to do this for escapes int identifiers as well. However, neither flow nor babylon preserves escapes in identifiers. For example, `\u0061.\u{0061}` cannot be distinguished from `a.a`. Nobody uses such escapes in real code anyway. It could also be considered a feature that such escapes are converted to real unicode characters. * Update snapshots * Normalize escapes in template literals * Update snapshotsmaster
parent
ea597182a9
commit
7148184d65
|
@ -729,7 +729,7 @@ function genericPrintNoParens(path, options, print) {
|
|||
case "NullLiteral":
|
||||
return "null"; // Babel 6 Literal split
|
||||
case "RegExpLiteral":
|
||||
return n.extra.raw;
|
||||
return printRegex(n);
|
||||
// Babel 6 Literal split
|
||||
case "NumericLiteral":
|
||||
return printNumber(n.extra.raw);
|
||||
|
@ -739,6 +739,7 @@ function genericPrintNoParens(path, options, print) {
|
|||
case "StringLiteral":
|
||||
case "Literal":
|
||||
if (typeof n.value === "number") return printNumber(n.raw);
|
||||
if (n.regex) return printRegex(n.regex);
|
||||
if (typeof n.value !== "string") return "" + n.value;
|
||||
|
||||
return nodeStr(n, options); // Babel 6
|
||||
|
@ -1233,7 +1234,10 @@ function genericPrintNoParens(path, options, print) {
|
|||
case "ClassExpression":
|
||||
return concat(printClass(path, options, print));
|
||||
case "TemplateElement":
|
||||
return join(literalline, n.value.raw.split("\n"));
|
||||
return join(
|
||||
literalline,
|
||||
n.value.raw.split("\n").map(line => normalizeEscapes(line))
|
||||
);
|
||||
case "TemplateLiteral":
|
||||
var expressions = path.map(print, "expressions");
|
||||
|
||||
|
@ -2524,7 +2528,37 @@ function makeString(rawContent, enclosingQuote) {
|
|||
return match;
|
||||
});
|
||||
|
||||
return enclosingQuote + newContent + enclosingQuote;
|
||||
return enclosingQuote + normalizeEscapes(newContent) + enclosingQuote;
|
||||
}
|
||||
|
||||
function printRegex(regexData) {
|
||||
const pattern = regexData.pattern;
|
||||
const flags = regexData.flags;
|
||||
const skipES2015 = !flags.includes("u");
|
||||
|
||||
return "/" + normalizeEscapes(pattern, skipES2015) + "/" + flags;
|
||||
}
|
||||
|
||||
function normalizeEscapes(rawContent, skipES2015) {
|
||||
// Matches \x escapes and \u escapes (including the ES2015 variant) and other
|
||||
// escapes.
|
||||
const regex = /(\\x[\da-f]{2}|\\u[\da-f]{4}|\\u\{[\da-f]+\})|(\\[\s\S])/gi;
|
||||
|
||||
return rawContent.replace(regex, (match, escape, otherEscape) => {
|
||||
// Return other escapes as-is.
|
||||
if (otherEscape) {
|
||||
return otherEscape;
|
||||
}
|
||||
|
||||
// Regexes without the /u flag do not support ES2015 unicode escapes, so
|
||||
// return the match as-is.
|
||||
if (skipES2015 && escape[2] === "{") {
|
||||
return escape;
|
||||
}
|
||||
|
||||
// Print all \x and \u escapes lowercase.
|
||||
return escape.toLowerCase();
|
||||
});
|
||||
}
|
||||
|
||||
function printNumber(rawNumber) {
|
||||
|
|
|
@ -116,3 +116,48 @@ function test5(): string {
|
|||
0.1e-10;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`test regex.js 1`] = `
|
||||
"// Normalization of \\x and \\u escapes:
|
||||
|
||||
// Basic case.
|
||||
/a\\xAaAb\\uB1cDE/gim;
|
||||
|
||||
// ES2015 unicode escapes.
|
||||
/\\u{1Fa3}/u;
|
||||
/\\u{00000000A0}/u;
|
||||
|
||||
// Leaves what looks like a ES2015 unicode escape alone if not using the /u flag.
|
||||
/\\u{1Fa3}/;
|
||||
|
||||
// Leaves what looks like escapes but aren\'t alone.
|
||||
/\\xA\\u00BG/;
|
||||
|
||||
// Leaves other escapes alone.
|
||||
/\\B\\S/;
|
||||
|
||||
// Handles escaped backslashes.
|
||||
/\\\\xAB\\\\\\xAB\\\\\\\\xAB\\B\\\\\\B\\uAbCd/;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Normalization of \\x and \\u escapes:
|
||||
|
||||
// Basic case.
|
||||
/a\\xaaAb\\ub1cdE/gim;
|
||||
|
||||
// ES2015 unicode escapes.
|
||||
/\\u{1fa3}/u;
|
||||
/\\u{00000000a0}/u;
|
||||
|
||||
// Leaves what looks like a ES2015 unicode escape alone if not using the /u flag.
|
||||
/\\u{1Fa3}/;
|
||||
|
||||
// Leaves what looks like escapes but aren\'t alone.
|
||||
/\\xA\\u00BG/;
|
||||
|
||||
// Leaves other escapes alone.
|
||||
/\\B\\S/;
|
||||
|
||||
// Handles escaped backslashes.
|
||||
/\\\\xAB\\\\\\xab\\\\\\\\xAB\\B\\\\\\B\\uabcd/;
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// Normalization of \x and \u escapes:
|
||||
|
||||
// Basic case.
|
||||
/a\xAaAb\uB1cDE/gim;
|
||||
|
||||
// ES2015 unicode escapes.
|
||||
/\u{1Fa3}/u;
|
||||
/\u{00000000A0}/u;
|
||||
|
||||
// Leaves what looks like a ES2015 unicode escape alone if not using the /u flag.
|
||||
/\u{1Fa3}/;
|
||||
|
||||
// Leaves what looks like escapes but aren't alone.
|
||||
/\xA\u00BG/;
|
||||
|
||||
// Leaves other escapes alone.
|
||||
/\B\S/;
|
||||
|
||||
// Handles escaped backslashes.
|
||||
/\\xAB\\\xAB\\\\xAB\B\\\B\uAbCd/;
|
|
@ -24,6 +24,29 @@ exports[`test strings.js 1`] = `
|
|||
|
||||
\'\\uD801\\uDC28\',
|
||||
];
|
||||
|
||||
// Normalization of \\x and \\u escapes:
|
||||
|
||||
// Basic case.
|
||||
\"a\\xAaAb\\uB1cDE\";
|
||||
\`a\\xAaAb\\uB1cDE\`;
|
||||
|
||||
// ES2015 unicode escapes.
|
||||
\"\\u{1Fa3}\";
|
||||
\`\\u{1Fa3}\`;
|
||||
\"\\u{00000000A0}\";
|
||||
\`\\u{00000000A0}\`;
|
||||
|
||||
// Leaves other escapes alone.
|
||||
\"\\B\\S\";
|
||||
\`\\B\\S\`;
|
||||
|
||||
// Handles escaped backslashes.
|
||||
\"\\\\xAB\\\\\\xAB\\\\\\\\xAB\\B\\\\\\B\\u1234\";
|
||||
\`\\\\xAB\\\\\\xAB\\\\\\\\xAB\\B\\\\\\B\\u1234\`;
|
||||
|
||||
// Mix of everything.
|
||||
\"\\xF0\"\`a\\uaBcD\${\'\\xFdE\'}\\\\\\u{00AbCdE}\`;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
[
|
||||
\"abc\",
|
||||
|
@ -42,6 +65,17 @@ exports[`test strings.js 1`] = `
|
|||
\"\\0\",
|
||||
\"🐶\",
|
||||
\'\\uD801\\uDC28\'
|
||||
];
|
||||
]; // Normalization of \\x and \\u escapes: // Basic case.
|
||||
\"a\\xaaAb\\ub1cdE\";
|
||||
\`a\\xaaAb\\ub1cdE\`; // ES2015 unicode escapes.
|
||||
\"\\u{1fa3}\";
|
||||
\`\\u{1fa3}\`;
|
||||
\"\\u{00000000a0}\";
|
||||
\`\\u{00000000a0}\`; // Leaves other escapes alone.
|
||||
\"\\B\\S\";
|
||||
\`\\B\\S\`; // Handles escaped backslashes.
|
||||
\"\\\\xAB\\\\\\xab\\\\\\\\xAB\\B\\\\\\B\\u1234\";
|
||||
\`\\\\xAB\\\\\\xab\\\\\\\\xAB\\B\\\\\\B\\u1234\`; // Mix of everything.
|
||||
\"\\xf0\"\`a\\uabcd\${\"\\xfdE\"}\\\\\\u{00abcde}\`;
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -23,3 +23,26 @@
|
|||
|
||||
'\uD801\uDC28',
|
||||
];
|
||||
|
||||
// Normalization of \x and \u escapes:
|
||||
|
||||
// Basic case.
|
||||
"a\xAaAb\uB1cDE";
|
||||
`a\xAaAb\uB1cDE`;
|
||||
|
||||
// ES2015 unicode escapes.
|
||||
"\u{1Fa3}";
|
||||
`\u{1Fa3}`;
|
||||
"\u{00000000A0}";
|
||||
`\u{00000000A0}`;
|
||||
|
||||
// Leaves other escapes alone.
|
||||
"\B\S";
|
||||
`\B\S`;
|
||||
|
||||
// Handles escaped backslashes.
|
||||
"\\xAB\\\xAB\\\\xAB\B\\\B\u1234";
|
||||
`\\xAB\\\xAB\\\\xAB\B\\\B\u1234`;
|
||||
|
||||
// Mix of everything.
|
||||
"\xF0"`a\uaBcD${'\xFdE'}\\\u{00AbCdE}`;
|
||||
|
|
Loading…
Reference in New Issue