diff --git a/lib/util.js b/lib/util.js index f56d812eee26f3..79fdb33326ebc9 100644 --- a/lib/util.js +++ b/lib/util.js @@ -17,7 +17,6 @@ function tryStringify(arg) { } } -const formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (typeof f !== 'string') { const objects = new Array(arguments.length); @@ -27,30 +26,56 @@ exports.format = function(f) { return objects.join(' '); } - if (arguments.length === 1) return f; - - const len = arguments.length; - const args = new Array(len); - var i; - for (i = 0; i < len; i++) { - args[i] = arguments[i]; - } - - i = 1; - var str = f.replace(formatRegExp, function(x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': return tryStringify(args[i++]); - // falls through - default: - return x; + var argLen = arguments.length; + + if (argLen === 1) return f; + + var str = ''; + var a = 1; + var lastPos = 0; + for (var i = 0; i < f.length;) { + if (f.charCodeAt(i) === 37/*'%'*/ && i + 1 < f.length) { + switch (f.charCodeAt(i + 1)) { + case 100: // 'd' + if (a >= argLen) + break; + if (lastPos < i) + str += f.slice(lastPos, i); + str += Number(arguments[a++]); + lastPos = i = i + 2; + continue; + case 106: // 'j' + if (a >= argLen) + break; + if (lastPos < i) + str += f.slice(lastPos, i); + str += tryStringify(arguments[a++]); + lastPos = i = i + 2; + continue; + case 115: // 's' + if (a >= argLen) + break; + if (lastPos < i) + str += f.slice(lastPos, i); + str += String(arguments[a++]); + lastPos = i = i + 2; + continue; + case 37: // '%' + if (lastPos < i) + str += f.slice(lastPos, i); + str += '%'; + lastPos = i = i + 2; + continue; + } } - }); - while (i < len) { - const x = args[i++]; + ++i; + } + if (lastPos === 0) + str = f; + else if (lastPos < f.length) + str += f.slice(lastPos); + while (a < argLen) { + const x = arguments[a++]; if (x === null || (typeof x !== 'object' && typeof x !== 'symbol')) { str += ' ' + x; } else {