@@ -209,7 +209,6 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
209209 return obj ;
210210 }
211211
212- var regexp = / \+ / g;
213212 qs = qs . split ( sep ) ;
214213
215214 var maxKeys = 1000 ;
@@ -230,7 +229,9 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
230229
231230 var keys = [ ] ;
232231 for ( var i = 0 ; i < len ; ++ i ) {
233- const x = qs [ i ] . replace ( regexp , '%20' ) ;
232+ // replacePlus() is used instead of a regexp because it is ~15-30% faster
233+ // with v8 4.7
234+ const x = replacePlus ( qs [ i ] ) ;
234235 const idx = x . indexOf ( eq ) ;
235236 var k , v ;
236237
@@ -242,10 +243,14 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
242243 v = '' ;
243244 }
244245
246+ // Use a key array lookup instead of using hasOwnProperty(), which is slower
245247 if ( keys . indexOf ( k ) === - 1 ) {
246248 obj [ k ] = v ;
247249 keys . push ( k ) ;
248- } else if ( Array . isArray ( obj [ k ] ) ) {
250+ } else if ( obj [ k ] instanceof Array ) {
251+ // `instanceof Array` is used instead of Array.isArray() because it is
252+ // ~15-20% faster with v8 4.7 and is safe to use because we are using it
253+ // with values being created within this function
249254 obj [ k ] . push ( v ) ;
250255 } else {
251256 obj [ k ] = [ obj [ k ] , v ] ;
@@ -256,6 +261,25 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
256261} ;
257262
258263
264+ function replacePlus ( str ) {
265+ var ret = '' ;
266+ var start = 0 ;
267+ var i = - 1 ;
268+ while ( ( i = str . indexOf ( '+' , i + 1 ) ) !== - 1 ) {
269+ ret += str . slice ( start , i ) ;
270+ ret += '%20' ;
271+ start = i + 1 ;
272+ }
273+ if ( start === 0 )
274+ return str ;
275+ if ( start < str . length )
276+ ret += str . slice ( start ) ;
277+ return ret ;
278+ }
279+
280+
281+ // v8 does not optimize functions with try-catch blocks, so we isolate them here
282+ // to minimize the damage
259283function decodeStr ( s , decoder ) {
260284 try {
261285 return decoder ( s ) ;
0 commit comments