aboutsummaryrefslogtreecommitdiff
path: root/lib/util.js
diff options
context:
space:
mode:
authorRuben Bridgewater <ruben@bridgewater.de>2018-07-02 20:52:34 +0200
committerRuben Bridgewater <ruben@bridgewater.de>2018-07-16 14:18:25 +0200
commitb3e93a91eb4e2c38c07550d61be899bd32137a0a (patch)
tree0ea0125536f18d7a41ce8c0d0594dde0306ead7e /lib/util.js
parent49681e7414629e0d3fbc3ac5bfbd3fa46725c49c (diff)
downloadandroid-node-v8-b3e93a91eb4e2c38c07550d61be899bd32137a0a.tar.gz
android-node-v8-b3e93a91eb4e2c38c07550d61be899bd32137a0a.tar.bz2
android-node-v8-b3e93a91eb4e2c38c07550d61be899bd32137a0a.zip
util: do not escape single quotes if not necessary
Right now util.inspect will always escape single quotes. That is not necessary though in case the string that will be escaped does not contain double quotes. In that case the string can simply be wrapped in double quotes instead. If the string contains single and double quotes and it does not contain `${` as part of the string, backticks will be used instead. That makes sure only very few strings have to escape quotes at all. Thus it increases the readability of these strings. PR-URL: https://github.com/nodejs/node/pull/21624 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'lib/util.js')
-rw-r--r--lib/util.js50
1 files changed, 44 insertions, 6 deletions
diff --git a/lib/util.js b/lib/util.js
index 5413cc0a33..c56b8429f4 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -90,6 +90,9 @@ let internalDeepEqual;
/* eslint-disable no-control-regex */
const strEscapeSequencesRegExp = /[\x00-\x1f\x27\x5c]/;
const strEscapeSequencesReplacer = /[\x00-\x1f\x27\x5c]/g;
+const strEscapeSequencesRegExpSingle = /[\x00-\x1f\x5c]/;
+const strEscapeSequencesReplacerSingle = /[\x00-\x1f\x5c]/g;
+
/* eslint-enable no-control-regex */
const keyStrRegExp = /^[a-zA-Z_][a-zA-Z_0-9]*$/;
@@ -116,21 +119,56 @@ const meta = [
'', '', '', '', '', '', '', '\\\\'
];
+function addQuotes(str, quotes) {
+ if (quotes === -1) {
+ return `"${str}"`;
+ }
+ if (quotes === -2) {
+ return `\`${str}\``;
+ }
+ return `'${str}'`;
+}
+
const escapeFn = (str) => meta[str.charCodeAt(0)];
// Escape control characters, single quotes and the backslash.
// This is similar to JSON stringify escaping.
function strEscape(str) {
+ let escapeTest = strEscapeSequencesRegExp;
+ let escapeReplace = strEscapeSequencesReplacer;
+ let singleQuote = 39;
+
+ // Check for double quotes. If not present, do not escape single quotes and
+ // instead wrap the text in double quotes. If double quotes exist, check for
+ // backticks. If they do not exist, use those as fallback instead of the
+ // double quotes.
+ if (str.indexOf("'") !== -1) {
+ // This invalidates the charCode and therefore can not be matched for
+ // anymore.
+ if (str.indexOf('"') === -1) {
+ singleQuote = -1;
+ } else if (str.indexOf('`') === -1 && str.indexOf('${') === -1) {
+ singleQuote = -2;
+ }
+ if (singleQuote !== 39) {
+ escapeTest = strEscapeSequencesRegExpSingle;
+ escapeReplace = strEscapeSequencesReplacerSingle;
+ }
+ }
+
// Some magic numbers that worked out fine while benchmarking with v8 6.0
- if (str.length < 5000 && !strEscapeSequencesRegExp.test(str))
- return `'${str}'`;
- if (str.length > 100)
- return `'${str.replace(strEscapeSequencesReplacer, escapeFn)}'`;
+ if (str.length < 5000 && !escapeTest.test(str))
+ return addQuotes(str, singleQuote);
+ if (str.length > 100) {
+ str = str.replace(escapeReplace, escapeFn);
+ return addQuotes(str, singleQuote);
+ }
+
let result = '';
let last = 0;
for (var i = 0; i < str.length; i++) {
const point = str.charCodeAt(i);
- if (point === 39 || point === 92 || point < 32) {
+ if (point === singleQuote || point === 92 || point < 32) {
if (last === i) {
result += meta[point];
} else {
@@ -144,7 +182,7 @@ function strEscape(str) {
} else if (last !== i) {
result += str.slice(last);
}
- return `'${result}'`;
+ return addQuotes(result, singleQuote);
}
function tryStringify(arg) {