From 800b266bd826aca14490be7b527cd1da03498f1f Mon Sep 17 00:00:00 2001 From: Ryan Hendrickson Date: Mon, 20 Nov 2017 13:37:13 -0500 Subject: [PATCH] refactor(lockfile): remove string concatenation from parsing code Replace all instances of building strings incrementally using += with more efficient methods. --- src/lockfile/parse.js | 49 +++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/src/lockfile/parse.js b/src/lockfile/parse.js index 4db0830ac4..65ea9297bb 100644 --- a/src/lockfile/parse.js +++ b/src/lockfile/parse.js @@ -69,44 +69,43 @@ function* tokenise(input: string): Iterator { } else if (input[0] === '#') { chop++; - let val = ''; - while (input[chop] !== '\n') { - val += input[chop]; - chop++; + let nextNewline = input.indexOf('\n', chop); + if (nextNewline === -1) { + nextNewline = input.length; } + const val = input.substring(chop, nextNewline); + chop = nextNewline; yield buildToken(TOKEN_TYPES.comment, val); } else if (input[0] === ' ') { if (lastNewline) { - let indent = ''; - for (let i = 0; input[i] === ' '; i++) { - indent += input[i]; + let indentSize = 1; + for (let i = 1; input[i] === ' '; i++) { + indentSize++; } - if (indent.length % 2) { + if (indentSize % 2) { throw new TypeError('Invalid number of spaces'); } else { - chop = indent.length; - yield buildToken(TOKEN_TYPES.indent, indent.length / 2); + chop = indentSize; + yield buildToken(TOKEN_TYPES.indent, indentSize / 2); } } else { chop++; } } else if (input[0] === '"') { - let val = ''; - - for (let i = 0; ; i++) { - const currentChar = input[i]; - val += currentChar; - - if (i > 0 && currentChar === '"') { + let i = 1; + for (; ; i++) { + if (input[i] === '"') { const isEscaped = input[i - 1] === '\\' && input[i - 2] !== '\\'; if (!isEscaped) { + i++; break; } } } + const val = input.substring(0, i); - chop = val.length; + chop = i; try { yield buildToken(TOKEN_TYPES.string, JSON.parse(val)); @@ -118,10 +117,7 @@ function* tokenise(input: string): Iterator { } } } else if (/^[0-9]/.test(input)) { - let val = ''; - for (let i = 0; /^[0-9]$/.test(input[i]); i++) { - val += input[i]; - } + const val = /^[0-9]+/.exec(input)[0]; chop = val.length; yield buildToken(TOKEN_TYPES.number, +val); @@ -138,16 +134,15 @@ function* tokenise(input: string): Iterator { yield buildToken(TOKEN_TYPES.comma); chop++; } else if (/^[a-zA-Z\/-]/g.test(input)) { - let name = ''; - for (let i = 0; i < input.length; i++) { + let i = 0; + for (; i < input.length; i++) { const char = input[i]; if (char === ':' || char === ' ' || char === '\n' || char === '\r' || char === ',') { break; - } else { - name += char; } } - chop = name.length; + const name = input.substring(0, i); + chop = i; yield buildToken(TOKEN_TYPES.string, name); } else {