From 05ce84a142a676e0a96fd9feed3184a2583b4aa0 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 2 Jul 2018 20:52:34 +0200 Subject: [PATCH 1/4] 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. --- lib/util.js | 32 ++++++++++++++++++++++++------ test/parallel/test-repl-colors.js | 2 +- test/parallel/test-util-inspect.js | 2 +- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/util.js b/lib/util.js index afd3cae724a6a7..cba768e02966f2 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]*$/; @@ -121,16 +124,33 @@ 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 (str.indexOf("'") !== -1 && str.indexOf('"') === -1) { + // This invalidates the charCode and therefore can not be matched for + // anymore. + singleQuote = -1; + 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 singleQuote === -1 ? `"${str}"` : `'${str}'`; + if (str.length > 100) { + str = str.replace(escapeReplace, escapeFn); + return singleQuote === -1 ? `"${str}"` : `'${str}'`; + } + 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 +164,7 @@ function strEscape(str) { } else if (last !== i) { result += str.slice(last); } - return `'${result}'`; + return singleQuote === -1 ? `"${result}"` : `'${result}'`; } function tryStringify(arg) { diff --git a/test/parallel/test-repl-colors.js b/test/parallel/test-repl-colors.js index dfcc020d899ee6..f484f57945a16b 100644 --- a/test/parallel/test-repl-colors.js +++ b/test/parallel/test-repl-colors.js @@ -24,7 +24,7 @@ process.on('exit', function() { // https://github.com/nodejs/node/pull/16485#issuecomment-350428638 // The color setting of the REPL should not have leaked over into // the color setting of `util.inspect.defaultOptions`. - strictEqual(output.includes(`'\\'string\\''`), true); + strictEqual(output.includes(`"'string'"`), true); strictEqual(output.includes(`'\u001b[32m\\'string\\'\u001b[39m'`), false); strictEqual(inspect.defaultOptions.colors, false); strictEqual(repl.writer.options.colors, true); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 1f05f4987eeb41..986043bc633bf3 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -47,7 +47,7 @@ assert.strictEqual(util.inspect(new Date('')), (new Date('')).toString()); assert.strictEqual(util.inspect('\n\u0001'), "'\\n\\u0001'"); assert.strictEqual( util.inspect(`${Array(75).fill(1)}'\n\u001d\n\u0003`), - `'${Array(75).fill(1)}\\'\\n\\u001d\\n\\u0003'` + `"${Array(75).fill(1)}'\\n\\u001d\\n\\u0003"` ); assert.strictEqual(util.inspect([]), '[]'); assert.strictEqual(util.inspect(Object.create([])), 'Array {}'); From 1c809692d19490ec20f895947470cc5ba2bb9deb Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 2 Jul 2018 22:43:29 +0200 Subject: [PATCH 2/4] util: reduce .inspect quote escaping This reduces the amount of quotes util.inspect escapes by falling back to backticks in case a string contains single and double quotes. That makes sure only very few strings have to escape quotes at all. Thus it increases the readability of these strings. --- lib/util.js | 34 +++++++++++++++++++++++------- test/parallel/test-util-inspect.js | 10 +++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/lib/util.js b/lib/util.js index cba768e02966f2..c6c9375e578c99 100644 --- a/lib/util.js +++ b/lib/util.js @@ -119,6 +119,16 @@ 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. @@ -129,21 +139,29 @@ function strEscape(str) { let singleQuote = 39; // Check for double quotes. If not present, do not escape single quotes and - // instead wrap the text in double quotes. - if (str.indexOf("'") !== -1 && str.indexOf('"') === -1) { + // 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. - singleQuote = -1; - escapeTest = strEscapeSequencesRegExpSingle; - escapeReplace = strEscapeSequencesReplacerSingle; + if (str.indexOf('"') === -1) { + singleQuote = -1; + } else if (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 && !escapeTest.test(str)) - return singleQuote === -1 ? `"${str}"` : `'${str}'`; + return addQuotes(str, singleQuote); if (str.length > 100) { str = str.replace(escapeReplace, escapeFn); - return singleQuote === -1 ? `"${str}"` : `'${str}'`; + return addQuotes(str, singleQuote); } let result = ''; @@ -164,7 +182,7 @@ function strEscape(str) { } else if (last !== i) { result += str.slice(last); } - return singleQuote === -1 ? `"${result}"` : `'${result}'`; + return addQuotes(result, singleQuote); } function tryStringify(arg) { diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 986043bc633bf3..bd98442608a792 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -1424,3 +1424,13 @@ util.inspect(process); assert(longList.includes('[Object: Inspection interrupted ' + 'prematurely. Maximum call stack size exceeded.]')); } + +// Do not escape single quotes if no double quote or backtick is present. +assert.strictEqual( + util.inspect("'"), + '"\'"' +); +assert.strictEqual( + util.inspect('"\''), + '`"\'`' +); From 86552346b5a08e6699cdb6bb17ff3fb7a2e0dd37 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 2 Jul 2018 22:47:53 +0200 Subject: [PATCH 3/4] test: improve inspect readability The string escaping is hard to read. This changes all those escaped strings to use double quotes instead so no escaping is necessary. --- test/parallel/test-util-inspect.js | 122 ++++++++++++++--------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index bd98442608a792..366887f59c3ddb 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -93,7 +93,7 @@ assert.strictEqual( Object.assign(new String('hello'), { [Symbol('foo')]: 123 }), { showHidden: true } ), - '{ [String: \'hello\'] [length]: 5, [Symbol(foo)]: 123 }' + "{ [String: 'hello'] [length]: 5, [Symbol(foo)]: 123 }" ); assert.strictEqual(util.inspect((new JSStream())._externalStream), @@ -265,7 +265,7 @@ assert.strictEqual( name: { value: 'Tim', enumerable: true }, hidden: { value: 'secret' } })), - '{ name: \'Tim\' }' + "{ name: 'Tim' }" ); // Dynamic properties. @@ -308,7 +308,7 @@ assert.strictEqual( } ); assert.strictEqual(util.inspect(value), - '[ 1, 2, 3, growingLength: [Getter], \'-1\': -1 ]'); + "[ 1, 2, 3, growingLength: [Getter], '-1': -1 ]"); } // Array with inherited number properties. @@ -422,24 +422,24 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); // Test for sparse array. { const a = ['foo', 'bar', 'baz']; - assert.strictEqual(util.inspect(a), '[ \'foo\', \'bar\', \'baz\' ]'); + assert.strictEqual(util.inspect(a), "[ 'foo', 'bar', 'baz' ]"); delete a[1]; - assert.strictEqual(util.inspect(a), '[ \'foo\', <1 empty item>, \'baz\' ]'); + assert.strictEqual(util.inspect(a), "[ 'foo', <1 empty item>, 'baz' ]"); assert.strictEqual( util.inspect(a, true), - '[ \'foo\', <1 empty item>, \'baz\', [length]: 3 ]' + "[ 'foo', <1 empty item>, 'baz', [length]: 3 ]" ); assert.strictEqual(util.inspect(new Array(5)), '[ <5 empty items> ]'); a[3] = 'bar'; a[100] = 'qux'; assert.strictEqual( util.inspect(a, { breakLength: Infinity }), - '[ \'foo\', <1 empty item>, \'baz\', \'bar\', <96 empty items>, \'qux\' ]' + "[ 'foo', <1 empty item>, 'baz', 'bar', <96 empty items>, 'qux' ]" ); delete a[3]; assert.strictEqual( util.inspect(a, { maxArrayLength: 4 }), - '[ \'foo\', <1 empty item>, \'baz\', <97 empty items>, ... 1 more item ]' + "[ 'foo', <1 empty item>, 'baz', <97 empty items>, ... 1 more item ]" ); } @@ -630,13 +630,13 @@ assert.strictEqual(util.inspect(Object.create(Date.prototype)), 'Date {}'); assert.strictEqual( util.inspect(w), - '{ \'\\\\\': 1, \'\\\\\\\\\': 2, \'\\\\\\\\\\\\\': 3, ' + - '\'\\\\\\\\\\\\\\\\\': 4, \'\\n\': 5, \'\\r\': 6 }' + "{ '\\\\': 1, '\\\\\\\\': 2, '\\\\\\\\\\\\': 3, " + + "'\\\\\\\\\\\\\\\\': 4, '\\n': 5, '\\r': 6 }" ); assert.strictEqual( util.inspect(y), - '[ \'a\', \'b\', \'c\', \'\\\\\\\\\': \'d\', ' + - '\'\\n\': \'e\', \'\\r\': \'f\' ]' + "[ 'a', 'b', 'c', '\\\\\\\\': 'd', " + + "'\\n': 'e', '\\r': 'f' ]" ); } @@ -733,7 +733,7 @@ util.inspect({ hasOwnProperty: null }); // A custom [util.inspect.custom]() should be able to return other Objects. subject[util.inspect.custom] = () => ({ foo: 'bar' }); - assert.strictEqual(util.inspect(subject), '{ foo: \'bar\' }'); + assert.strictEqual(util.inspect(subject), "{ foo: 'bar' }"); subject[util.inspect.custom] = (depth, opts) => { assert.strictEqual(opts.customInspectOptions, true); @@ -776,7 +776,7 @@ util.inspect({ hasOwnProperty: null }); } // Test boxed primitives output the correct values. -assert.strictEqual(util.inspect(new String('test')), '[String: \'test\']'); +assert.strictEqual(util.inspect(new String('test')), "[String: 'test']"); assert.strictEqual( util.inspect(Object(Symbol('test'))), '[Symbol: Symbol(test)]' @@ -792,15 +792,15 @@ assert.strictEqual(util.inspect(new Number(13.37)), '[Number: 13.37]'); { const str = new String('baz'); str.foo = 'bar'; - assert.strictEqual(util.inspect(str), '{ [String: \'baz\'] foo: \'bar\' }'); + assert.strictEqual(util.inspect(str), "{ [String: 'baz'] foo: 'bar' }"); const bool = new Boolean(true); bool.foo = 'bar'; - assert.strictEqual(util.inspect(bool), '{ [Boolean: true] foo: \'bar\' }'); + assert.strictEqual(util.inspect(bool), "{ [Boolean: true] foo: 'bar' }"); const num = new Number(13.37); num.foo = 'bar'; - assert.strictEqual(util.inspect(num), '{ [Number: 13.37] foo: \'bar\' }'); + assert.strictEqual(util.inspect(num), "{ [Number: 13.37] foo: 'bar' }"); } // Test es6 Symbol. @@ -829,7 +829,7 @@ if (typeof Symbol !== 'undefined') { assert.strictEqual(util.inspect(subject), '{ [Symbol(symbol)]: 42 }'); assert.strictEqual( util.inspect(subject, options), - '{ [Symbol(symbol)]: 42, [Symbol()]: \'non-enum\' }' + "{ [Symbol(symbol)]: 42, [Symbol()]: 'non-enum' }" ); subject = [1, 2, 3]; @@ -847,7 +847,7 @@ if (typeof Symbol !== 'undefined') { set.bar = 42; assert.strictEqual( util.inspect(set, true), - 'Set { \'foo\', [size]: 1, bar: 42 }' + "Set { 'foo', [size]: 1, bar: 42 }" ); } @@ -862,11 +862,11 @@ if (typeof Symbol !== 'undefined') { { assert.strictEqual(util.inspect(new Map()), 'Map {}'); assert.strictEqual(util.inspect(new Map([[1, 'a'], [2, 'b'], [3, 'c']])), - 'Map { 1 => \'a\', 2 => \'b\', 3 => \'c\' }'); + "Map { 1 => 'a', 2 => 'b', 3 => 'c' }"); const map = new Map([['foo', null]]); map.bar = 42; assert.strictEqual(util.inspect(map, true), - 'Map { \'foo\' => null, [size]: 1, bar: 42 }'); + "Map { 'foo' => null, [size]: 1, bar: 42 }"); } // Test circular Map. @@ -897,7 +897,7 @@ if (typeof Symbol !== 'undefined') { const promiseWithProperty = Promise.resolve('foo'); promiseWithProperty.bar = 42; assert.strictEqual(util.inspect(promiseWithProperty), - 'Promise { \'foo\', bar: 42 }'); + "Promise { 'foo', bar: 42 }"); } // Make sure it doesn't choke on polyfills. Unlike Set/Map, there is no standard @@ -913,14 +913,14 @@ if (typeof Symbol !== 'undefined') { // Test Map iterators. { const map = new Map([['foo', 'bar']]); - assert.strictEqual(util.inspect(map.keys()), '[Map Iterator] { \'foo\' }'); - assert.strictEqual(util.inspect(map.values()), '[Map Iterator] { \'bar\' }'); + assert.strictEqual(util.inspect(map.keys()), "[Map Iterator] { 'foo' }"); + assert.strictEqual(util.inspect(map.values()), "[Map Iterator] { 'bar' }"); assert.strictEqual(util.inspect(map.entries()), - '[Map Iterator] { [ \'foo\', \'bar\' ] }'); + "[Map Iterator] { [ 'foo', 'bar' ] }"); // Make sure the iterator doesn't get consumed. const keys = map.keys(); - assert.strictEqual(util.inspect(keys), '[Map Iterator] { \'foo\' }'); - assert.strictEqual(util.inspect(keys), '[Map Iterator] { \'foo\' }'); + assert.strictEqual(util.inspect(keys), "[Map Iterator] { 'foo' }"); + assert.strictEqual(util.inspect(keys), "[Map Iterator] { 'foo' }"); keys.extra = true; assert.strictEqual( util.inspect(keys, { maxArrayLength: 0 }), @@ -995,7 +995,7 @@ if (typeof Symbol !== 'undefined') { assert.strictEqual(util.inspect(new SetSubclass([1, 2, 3])), 'SetSubclass [Set] { 1, 2, 3 }'); assert.strictEqual(util.inspect(new MapSubclass([['foo', 42]])), - 'MapSubclass [Map] { \'foo\' => 42 }'); + "MapSubclass [Map] { 'foo' => 42 }"); assert.strictEqual(util.inspect(new PromiseSubclass(() => {})), 'PromiseSubclass [Promise] { }'); assert.strictEqual( @@ -1048,7 +1048,7 @@ if (typeof Symbol !== 'undefined') { { const x = []; x[''] = 1; - assert.strictEqual(util.inspect(x), '[ \'\': 1 ]'); + assert.strictEqual(util.inspect(x), "[ '': 1 ]"); } // The following maxArrayLength tests were introduced after v6.0.0 was released. @@ -1094,10 +1094,10 @@ if (typeof Symbol !== 'undefined') { const breakpoint = oneLine.length - 5; const twoLines = util.inspect(obj, { breakLength: breakpoint }); - assert.strictEqual(oneLine, '{ foo: \'abc\', bar: \'xyz\' }'); + assert.strictEqual(oneLine, "{ foo: 'abc', bar: 'xyz' }"); assert.strictEqual(oneLine, util.inspect(obj, { breakLength: breakpoint + 1 })); - assert.strictEqual(twoLines, '{ foo: \'abc\',\n bar: \'xyz\' }'); + assert.strictEqual(twoLines, "{ foo: 'abc',\n bar: 'xyz' }"); } // util.inspect.defaultOptions tests. @@ -1168,7 +1168,7 @@ util.inspect(process); { // @@toStringTag assert.strictEqual(util.inspect({ [Symbol.toStringTag]: 'a' }), - 'Object [a] { [Symbol(Symbol.toStringTag)]: \'a\' }'); + "Object [a] { [Symbol(Symbol.toStringTag)]: 'a' }"); class Foo { constructor() { @@ -1184,17 +1184,17 @@ util.inspect(process); Object.create(null, { [Symbol.toStringTag]: { value: 'foo' } })), '[foo] {}'); - assert.strictEqual(util.inspect(new Foo()), 'Foo [bar] { foo: \'bar\' }'); + assert.strictEqual(util.inspect(new Foo()), "Foo [bar] { foo: 'bar' }"); assert.strictEqual( util.inspect(new (class extends Foo {})()), - 'Foo [bar] { foo: \'bar\' }'); + "Foo [bar] { foo: 'bar' }"); assert.strictEqual( util.inspect(Object.create(Object.create(Foo.prototype), { foo: { value: 'bar', enumerable: true } })), - 'Foo [bar] { foo: \'bar\' }'); + "Foo [bar] { foo: 'bar' }"); class ThrowingClass { get [Symbol.toStringTag]() { @@ -1246,19 +1246,19 @@ util.inspect(process); ' 2,', ' [', ' [', - ' \'Lorem ipsum dolor\\nsit amet,\\tconsectetur \' +', - ' \'adipiscing elit, sed do eiusmod tempor \' +', - ' \'incididunt ut labore et dolore magna \' +', - ' \'aliqua.\',', - ' \'test\',', - ' \'foo\'', + " 'Lorem ipsum dolor\\nsit amet,\\tconsectetur ' +", + " 'adipiscing elit, sed do eiusmod tempor ' +", + " 'incididunt ut labore et dolore magna ' +", + " 'aliqua.',", + " 'test',", + " 'foo'", ' ]', ' ],', ' 4', ' ],', ' b: Map {', - ' \'za\' => 1,', - ' \'zb\' => \'test\'', + " 'za' => 1,", + " 'zb' => 'test'", ' }', '}' ].join('\n'); @@ -1266,28 +1266,28 @@ util.inspect(process); out = util.inspect(o.a[2][0][0], { compact: false, breakLength: 30 }); expect = [ - '\'Lorem ipsum dolor\\nsit \' +', - ' \'amet,\\tconsectetur \' +', - ' \'adipiscing elit, sed do \' +', - ' \'eiusmod tempor incididunt \' +', - ' \'ut labore et dolore magna \' +', - ' \'aliqua.\'' + "'Lorem ipsum dolor\\nsit ' +", + " 'amet,\\tconsectetur ' +", + " 'adipiscing elit, sed do ' +", + " 'eiusmod tempor incididunt ' +", + " 'ut labore et dolore magna ' +", + " 'aliqua.'" ].join('\n'); assert.strictEqual(out, expect); out = util.inspect( '12345678901234567890123456789012345678901234567890', { compact: false, breakLength: 3 }); - expect = '\'12345678901234567890123456789012345678901234567890\''; + expect = "'12345678901234567890123456789012345678901234567890'"; assert.strictEqual(out, expect); out = util.inspect( '12 45 78 01 34 67 90 23 56 89 123456789012345678901234567890', { compact: false, breakLength: 3 }); expect = [ - '\'12 45 78 01 34 \' +', - ' \'67 90 23 56 89 \' +', - ' \'123456789012345678901234567890\'' + "'12 45 78 01 34 ' +", + " '67 90 23 56 89 ' +", + " '123456789012345678901234567890'" ].join('\n'); assert.strictEqual(out, expect); @@ -1295,9 +1295,9 @@ util.inspect(process); '12 45 78 01 34 67 90 23 56 89 1234567890123 0', { compact: false, breakLength: 3 }); expect = [ - '\'12 45 78 01 34 \' +', - ' \'67 90 23 56 89 \' +', - ' \'1234567890123 0\'' + "'12 45 78 01 34 ' +", + " '67 90 23 56 89 ' +", + " '1234567890123 0'" ].join('\n'); assert.strictEqual(out, expect); @@ -1305,10 +1305,10 @@ util.inspect(process); '12 45 78 01 34 67 90 23 56 89 12345678901234567 0', { compact: false, breakLength: 3 }); expect = [ - '\'12 45 78 01 34 \' +', - ' \'67 90 23 56 89 \' +', - ' \'12345678901234567 \' +', - ' \'0\'' + "'12 45 78 01 34 ' +", + " '67 90 23 56 89 ' +", + " '12345678901234567 ' +", + " '0'" ].join('\n'); assert.strictEqual(out, expect); @@ -1347,7 +1347,7 @@ util.inspect(process); o[util.inspect.custom] = () => ({ a: '12 45 78 01 34 67 90 23' }); out = util.inspect(o, { compact: false, breakLength: 3 }); - expect = '{\n a: \'12 45 78 01 34 \' +\n \'67 90 23\'\n}'; + expect = "{\n a: '12 45 78 01 34 ' +\n '67 90 23'\n}"; assert.strictEqual(out, expect); } From 97f78ded2a0ba8334ddf2e0c6b4db3ead93dc91b Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 4 Jul 2018 11:04:10 +0200 Subject: [PATCH 4/4] fixup: address comment --- lib/util.js | 2 +- test/parallel/test-util-inspect.js | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/util.js b/lib/util.js index c6c9375e578c99..8fd1e204cd470d 100644 --- a/lib/util.js +++ b/lib/util.js @@ -147,7 +147,7 @@ function strEscape(str) { // anymore. if (str.indexOf('"') === -1) { singleQuote = -1; - } else if (str.indexOf('`') === -1) { + } else if (str.indexOf('`') === -1 && str.indexOf('${') === -1) { singleQuote = -2; } if (singleQuote !== 39) { diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 366887f59c3ddb..b5b622b49e60e4 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -1426,11 +1426,7 @@ util.inspect(process); } // Do not escape single quotes if no double quote or backtick is present. -assert.strictEqual( - util.inspect("'"), - '"\'"' -); -assert.strictEqual( - util.inspect('"\''), - '`"\'`' -); +assert.strictEqual(util.inspect("'"), '"\'"'); +assert.strictEqual(util.inspect('"\''), '`"\'`'); +// eslint-disable-next-line no-template-curly-in-string +assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'");