qs 6.3.3 → 6.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/qs.js CHANGED
@@ -1,4 +1,4 @@
1
- (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
1
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
2
  'use strict';
3
3
 
4
4
  var replace = String.prototype.replace;
@@ -11,7 +11,7 @@ module.exports = {
11
11
  return replace.call(value, percentTwenties, '+');
12
12
  },
13
13
  RFC3986: function (value) {
14
- return String(value);
14
+ return value;
15
15
  }
16
16
  },
17
17
  RFC1738: 'RFC1738',
@@ -52,19 +52,23 @@ var defaults = {
52
52
 
53
53
  var parseValues = function parseQueryStringValues(str, options) {
54
54
  var obj = {};
55
- var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
55
+ var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
56
+ var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
57
+ var parts = cleanStr.split(options.delimiter, limit);
56
58
 
57
59
  for (var i = 0; i < parts.length; ++i) {
58
60
  var part = parts[i];
59
- var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1;
61
+
62
+ var bracketEqualsPos = part.indexOf(']=');
63
+ var pos = bracketEqualsPos === -1 ? part.indexOf('=') : bracketEqualsPos + 1;
60
64
 
61
65
  var key, val;
62
66
  if (pos === -1) {
63
- key = options.decoder(part);
67
+ key = options.decoder(part, defaults.decoder);
64
68
  val = options.strictNullHandling ? null : '';
65
69
  } else {
66
- key = options.decoder(part.slice(0, pos));
67
- val = options.decoder(part.slice(pos + 1));
70
+ key = options.decoder(part.slice(0, pos), defaults.decoder);
71
+ val = options.decoder(part.slice(pos + 1), defaults.decoder);
68
72
  }
69
73
  if (has.call(obj, key)) {
70
74
  obj[key] = [].concat(obj[key]).concat(val);
@@ -76,38 +80,38 @@ var parseValues = function parseQueryStringValues(str, options) {
76
80
  return obj;
77
81
  };
78
82
 
79
- var parseObject = function parseObjectRecursive(chain, val, options) {
80
- if (!chain.length) {
81
- return val;
82
- }
83
+ var parseObject = function (chain, val, options) {
84
+ var leaf = val;
83
85
 
84
- var root = chain.shift();
86
+ for (var i = chain.length - 1; i >= 0; --i) {
87
+ var obj;
88
+ var root = chain[i];
85
89
 
86
- var obj;
87
- if (root === '[]' && options.parseArrays) {
88
- obj = [];
89
- obj = obj.concat(parseObject(chain, val, options));
90
- } else {
91
- obj = options.plainObjects ? Object.create(null) : {};
92
- var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
93
- var index = parseInt(cleanRoot, 10);
94
- if (!options.parseArrays && cleanRoot === '') {
95
- obj = { 0: val };
96
- } else if (
97
- !isNaN(index)
98
- && root !== cleanRoot
99
- && String(index) === cleanRoot
100
- && index >= 0
101
- && (options.parseArrays && index <= options.arrayLimit)
102
- ) {
90
+ if (root === '[]') {
103
91
  obj = [];
104
- obj[index] = parseObject(chain, val, options);
105
- } else if (cleanRoot !== '__proto__') {
106
- obj[cleanRoot] = parseObject(chain, val, options);
92
+ obj = obj.concat(leaf);
93
+ } else {
94
+ obj = options.plainObjects ? Object.create(null) : {};
95
+ var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
96
+ var index = parseInt(cleanRoot, 10);
97
+ if (
98
+ !isNaN(index)
99
+ && root !== cleanRoot
100
+ && String(index) === cleanRoot
101
+ && index >= 0
102
+ && (options.parseArrays && index <= options.arrayLimit)
103
+ ) {
104
+ obj = [];
105
+ obj[index] = leaf;
106
+ } else {
107
+ obj[cleanRoot] = leaf;
108
+ }
107
109
  }
110
+
111
+ leaf = obj;
108
112
  }
109
113
 
110
- return obj;
114
+ return leaf;
111
115
  };
112
116
 
113
117
  var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
@@ -132,7 +136,8 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
132
136
 
133
137
  var keys = [];
134
138
  if (parent) {
135
- // If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties
139
+ // If we aren't using plain objects, optionally prefix keys
140
+ // that would overwrite object prototype properties
136
141
  if (!options.plainObjects && has.call(Object.prototype, parent)) {
137
142
  if (!options.allowPrototypes) {
138
143
  return;
@@ -165,12 +170,13 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
165
170
  };
166
171
 
167
172
  module.exports = function (str, opts) {
168
- var options = opts || {};
173
+ var options = opts ? utils.assign({}, opts) : {};
169
174
 
170
175
  if (options.decoder !== null && options.decoder !== undefined && typeof options.decoder !== 'function') {
171
176
  throw new TypeError('Decoder has to be a function.');
172
177
  }
173
178
 
179
+ options.ignoreQueryPrefix = options.ignoreQueryPrefix === true;
174
180
  options.delimiter = typeof options.delimiter === 'string' || utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter;
175
181
  options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth;
176
182
  options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;
@@ -208,37 +214,32 @@ var utils = require('./utils');
208
214
  var formats = require('./formats');
209
215
 
210
216
  var arrayPrefixGenerators = {
211
- brackets: function brackets(prefix) {
217
+ brackets: function brackets(prefix) { // eslint-disable-line func-name-matching
212
218
  return prefix + '[]';
213
219
  },
214
- indices: function indices(prefix, key) {
220
+ indices: function indices(prefix, key) { // eslint-disable-line func-name-matching
215
221
  return prefix + '[' + key + ']';
216
222
  },
217
- repeat: function repeat(prefix) {
223
+ repeat: function repeat(prefix) { // eslint-disable-line func-name-matching
218
224
  return prefix;
219
225
  }
220
226
  };
221
227
 
222
- var isArray = Array.isArray;
223
- var push = Array.prototype.push;
224
- var pushToArray = function (arr, valueOrArray) {
225
- push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
226
- };
227
-
228
228
  var toISO = Date.prototype.toISOString;
229
229
 
230
230
  var defaults = {
231
231
  delimiter: '&',
232
232
  encode: true,
233
233
  encoder: utils.encode,
234
- serializeDate: function serializeDate(date) {
234
+ encodeValuesOnly: false,
235
+ serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching
235
236
  return toISO.call(date);
236
237
  },
237
238
  skipNulls: false,
238
239
  strictNullHandling: false
239
240
  };
240
241
 
241
- var stringify = function stringify(
242
+ var stringify = function stringify( // eslint-disable-line func-name-matching
242
243
  object,
243
244
  prefix,
244
245
  generateArrayPrefix,
@@ -249,18 +250,17 @@ var stringify = function stringify(
249
250
  sort,
250
251
  allowDots,
251
252
  serializeDate,
252
- formatter
253
+ formatter,
254
+ encodeValuesOnly
253
255
  ) {
254
256
  var obj = object;
255
257
  if (typeof filter === 'function') {
256
258
  obj = filter(prefix, obj);
257
259
  } else if (obj instanceof Date) {
258
260
  obj = serializeDate(obj);
259
- }
260
-
261
- if (obj === null) {
261
+ } else if (obj === null) {
262
262
  if (strictNullHandling) {
263
- return encoder ? encoder(prefix) : prefix;
263
+ return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder) : prefix;
264
264
  }
265
265
 
266
266
  obj = '';
@@ -268,7 +268,8 @@ var stringify = function stringify(
268
268
 
269
269
  if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
270
270
  if (encoder) {
271
- return [formatter(encoder(prefix)) + '=' + formatter(encoder(obj))];
271
+ var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder);
272
+ return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder))];
272
273
  }
273
274
  return [formatter(prefix) + '=' + formatter(String(obj))];
274
275
  }
@@ -280,7 +281,7 @@ var stringify = function stringify(
280
281
  }
281
282
 
282
283
  var objKeys;
283
- if (isArray(filter)) {
284
+ if (Array.isArray(filter)) {
284
285
  objKeys = filter;
285
286
  } else {
286
287
  var keys = Object.keys(obj);
@@ -294,8 +295,8 @@ var stringify = function stringify(
294
295
  continue;
295
296
  }
296
297
 
297
- if (isArray(obj)) {
298
- pushToArray(values, stringify(
298
+ if (Array.isArray(obj)) {
299
+ values = values.concat(stringify(
299
300
  obj[key],
300
301
  generateArrayPrefix(prefix, key),
301
302
  generateArrayPrefix,
@@ -306,10 +307,11 @@ var stringify = function stringify(
306
307
  sort,
307
308
  allowDots,
308
309
  serializeDate,
309
- formatter
310
+ formatter,
311
+ encodeValuesOnly
310
312
  ));
311
313
  } else {
312
- pushToArray(values, stringify(
314
+ values = values.concat(stringify(
313
315
  obj[key],
314
316
  prefix + (allowDots ? '.' + key : '[' + key + ']'),
315
317
  generateArrayPrefix,
@@ -320,7 +322,8 @@ var stringify = function stringify(
320
322
  sort,
321
323
  allowDots,
322
324
  serializeDate,
323
- formatter
325
+ formatter,
326
+ encodeValuesOnly
324
327
  ));
325
328
  }
326
329
  }
@@ -330,9 +333,9 @@ var stringify = function stringify(
330
333
 
331
334
  module.exports = function (object, opts) {
332
335
  var obj = object;
333
- var options = opts || {};
336
+ var options = opts ? utils.assign({}, opts) : {};
334
337
 
335
- if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') {
338
+ if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
336
339
  throw new TypeError('Encoder has to be a function.');
337
340
  }
338
341
 
@@ -340,10 +343,11 @@ module.exports = function (object, opts) {
340
343
  var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling;
341
344
  var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : defaults.skipNulls;
342
345
  var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode;
343
- var encoder = encode ? typeof options.encoder === 'function' ? options.encoder : defaults.encoder : null;
346
+ var encoder = typeof options.encoder === 'function' ? options.encoder : defaults.encoder;
344
347
  var sort = typeof options.sort === 'function' ? options.sort : null;
345
348
  var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
346
349
  var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
350
+ var encodeValuesOnly = typeof options.encodeValuesOnly === 'boolean' ? options.encodeValuesOnly : defaults.encodeValuesOnly;
347
351
  if (typeof options.format === 'undefined') {
348
352
  options.format = formats['default'];
349
353
  } else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
@@ -356,7 +360,7 @@ module.exports = function (object, opts) {
356
360
  if (typeof options.filter === 'function') {
357
361
  filter = options.filter;
358
362
  obj = filter('', obj);
359
- } else if (isArray(options.filter)) {
363
+ } else if (Array.isArray(options.filter)) {
360
364
  filter = options.filter;
361
365
  objKeys = filter;
362
366
  }
@@ -392,22 +396,27 @@ module.exports = function (object, opts) {
392
396
  if (skipNulls && obj[key] === null) {
393
397
  continue;
394
398
  }
395
- pushToArray(keys, stringify(
399
+
400
+ keys = keys.concat(stringify(
396
401
  obj[key],
397
402
  key,
398
403
  generateArrayPrefix,
399
404
  strictNullHandling,
400
405
  skipNulls,
401
- encoder,
406
+ encode ? encoder : null,
402
407
  filter,
403
408
  sort,
404
409
  allowDots,
405
410
  serializeDate,
406
- formatter
411
+ formatter,
412
+ encodeValuesOnly
407
413
  ));
408
414
  }
409
415
 
410
- return keys.join(delimiter);
416
+ var joined = keys.join(delimiter);
417
+ var prefix = options.addQueryPrefix === true ? '?' : '';
418
+
419
+ return joined.length > 0 ? prefix + joined : '';
411
420
  };
412
421
 
413
422
  },{"./formats":1,"./utils":5}],5:[function(require,module,exports){
@@ -424,7 +433,30 @@ var hexTable = (function () {
424
433
  return array;
425
434
  }());
426
435
 
427
- exports.arrayToObject = function (source, options) {
436
+ var compactQueue = function compactQueue(queue) {
437
+ var obj;
438
+
439
+ while (queue.length) {
440
+ var item = queue.pop();
441
+ obj = item.obj[item.prop];
442
+
443
+ if (Array.isArray(obj)) {
444
+ var compacted = [];
445
+
446
+ for (var j = 0; j < obj.length; ++j) {
447
+ if (typeof obj[j] !== 'undefined') {
448
+ compacted.push(obj[j]);
449
+ }
450
+ }
451
+
452
+ item.obj[item.prop] = compacted;
453
+ }
454
+ }
455
+
456
+ return obj;
457
+ };
458
+
459
+ exports.arrayToObject = function arrayToObject(source, options) {
428
460
  var obj = options && options.plainObjects ? Object.create(null) : {};
429
461
  for (var i = 0; i < source.length; ++i) {
430
462
  if (typeof source[i] !== 'undefined') {
@@ -435,7 +467,7 @@ exports.arrayToObject = function (source, options) {
435
467
  return obj;
436
468
  };
437
469
 
438
- exports.merge = function (target, source, options) {
470
+ exports.merge = function merge(target, source, options) {
439
471
  if (!source) {
440
472
  return target;
441
473
  }
@@ -443,8 +475,8 @@ exports.merge = function (target, source, options) {
443
475
  if (typeof source !== 'object') {
444
476
  if (Array.isArray(target)) {
445
477
  target.push(source);
446
- } else if (target && typeof target === 'object') {
447
- if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
478
+ } else if (typeof target === 'object') {
479
+ if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
448
480
  target[source] = true;
449
481
  }
450
482
  } else {
@@ -454,7 +486,7 @@ exports.merge = function (target, source, options) {
454
486
  return target;
455
487
  }
456
488
 
457
- if (!target || typeof target !== 'object') {
489
+ if (typeof target !== 'object') {
458
490
  return [target].concat(source);
459
491
  }
460
492
 
@@ -481,7 +513,7 @@ exports.merge = function (target, source, options) {
481
513
  return Object.keys(source).reduce(function (acc, key) {
482
514
  var value = source[key];
483
515
 
484
- if (Object.prototype.hasOwnProperty.call(acc, key)) {
516
+ if (has.call(acc, key)) {
485
517
  acc[key] = exports.merge(acc[key], value, options);
486
518
  } else {
487
519
  acc[key] = value;
@@ -490,6 +522,13 @@ exports.merge = function (target, source, options) {
490
522
  }, mergeTarget);
491
523
  };
492
524
 
525
+ exports.assign = function assignSingleSource(target, source) {
526
+ return Object.keys(source).reduce(function (acc, key) {
527
+ acc[key] = source[key];
528
+ return acc;
529
+ }, target);
530
+ };
531
+
493
532
  exports.decode = function (str) {
494
533
  try {
495
534
  return decodeURIComponent(str.replace(/\+/g, ' '));
@@ -498,7 +537,7 @@ exports.decode = function (str) {
498
537
  }
499
538
  };
500
539
 
501
- exports.encode = function (str) {
540
+ exports.encode = function encode(str) {
502
541
  // This code was originally written by Brian White (mscdex) for the io.js core querystring library.
503
542
  // It has been adapted here for stricter adherence to RFC 3986
504
543
  if (str.length === 0) {
@@ -541,7 +580,6 @@ exports.encode = function (str) {
541
580
 
542
581
  i += 1;
543
582
  c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
544
- /* eslint operator-linebreak: [2, "before"] */
545
583
  out += hexTable[0xF0 | (c >> 18)]
546
584
  + hexTable[0x80 | ((c >> 12) & 0x3F)]
547
585
  + hexTable[0x80 | ((c >> 6) & 0x3F)]
@@ -551,46 +589,33 @@ exports.encode = function (str) {
551
589
  return out;
552
590
  };
553
591
 
554
- exports.compact = function (obj, references) {
555
- if (typeof obj !== 'object' || obj === null) {
556
- return obj;
557
- }
558
-
559
- var refs = references || [];
560
- var lookup = refs.indexOf(obj);
561
- if (lookup !== -1) {
562
- return refs[lookup];
563
- }
564
-
565
- refs.push(obj);
592
+ exports.compact = function compact(value) {
593
+ var queue = [{ obj: { o: value }, prop: 'o' }];
594
+ var refs = [];
566
595
 
567
- if (Array.isArray(obj)) {
568
- var compacted = [];
596
+ for (var i = 0; i < queue.length; ++i) {
597
+ var item = queue[i];
598
+ var obj = item.obj[item.prop];
569
599
 
570
- for (var i = 0; i < obj.length; ++i) {
571
- if (obj[i] && typeof obj[i] === 'object') {
572
- compacted.push(exports.compact(obj[i], refs));
573
- } else if (typeof obj[i] !== 'undefined') {
574
- compacted.push(obj[i]);
600
+ var keys = Object.keys(obj);
601
+ for (var j = 0; j < keys.length; ++j) {
602
+ var key = keys[j];
603
+ var val = obj[key];
604
+ if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
605
+ queue.push({ obj: obj, prop: key });
606
+ refs.push(val);
575
607
  }
576
608
  }
577
-
578
- return compacted;
579
609
  }
580
610
 
581
- var keys = Object.keys(obj);
582
- keys.forEach(function (key) {
583
- obj[key] = exports.compact(obj[key], refs);
584
- });
585
-
586
- return obj;
611
+ return compactQueue(queue);
587
612
  };
588
613
 
589
- exports.isRegExp = function (obj) {
614
+ exports.isRegExp = function isRegExp(obj) {
590
615
  return Object.prototype.toString.call(obj) === '[object RegExp]';
591
616
  };
592
617
 
593
- exports.isBuffer = function (obj) {
618
+ exports.isBuffer = function isBuffer(obj) {
594
619
  if (obj === null || typeof obj === 'undefined') {
595
620
  return false;
596
621
  }
@@ -599,4 +624,4 @@ exports.isBuffer = function (obj) {
599
624
  };
600
625
 
601
626
  },{}]},{},[2])(2)
602
- });
627
+ });
package/lib/formats.js CHANGED
@@ -10,7 +10,7 @@ module.exports = {
10
10
  return replace.call(value, percentTwenties, '+');
11
11
  },
12
12
  RFC3986: function (value) {
13
- return String(value);
13
+ return value;
14
14
  }
15
15
  },
16
16
  RFC1738: 'RFC1738',
package/lib/parse.js CHANGED
@@ -18,19 +18,23 @@ var defaults = {
18
18
 
19
19
  var parseValues = function parseQueryStringValues(str, options) {
20
20
  var obj = {};
21
- var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
21
+ var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
22
+ var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
23
+ var parts = cleanStr.split(options.delimiter, limit);
22
24
 
23
25
  for (var i = 0; i < parts.length; ++i) {
24
26
  var part = parts[i];
25
- var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1;
27
+
28
+ var bracketEqualsPos = part.indexOf(']=');
29
+ var pos = bracketEqualsPos === -1 ? part.indexOf('=') : bracketEqualsPos + 1;
26
30
 
27
31
  var key, val;
28
32
  if (pos === -1) {
29
- key = options.decoder(part);
33
+ key = options.decoder(part, defaults.decoder);
30
34
  val = options.strictNullHandling ? null : '';
31
35
  } else {
32
- key = options.decoder(part.slice(0, pos));
33
- val = options.decoder(part.slice(pos + 1));
36
+ key = options.decoder(part.slice(0, pos), defaults.decoder);
37
+ val = options.decoder(part.slice(pos + 1), defaults.decoder);
34
38
  }
35
39
  if (has.call(obj, key)) {
36
40
  obj[key] = [].concat(obj[key]).concat(val);
@@ -42,38 +46,38 @@ var parseValues = function parseQueryStringValues(str, options) {
42
46
  return obj;
43
47
  };
44
48
 
45
- var parseObject = function parseObjectRecursive(chain, val, options) {
46
- if (!chain.length) {
47
- return val;
48
- }
49
+ var parseObject = function (chain, val, options) {
50
+ var leaf = val;
49
51
 
50
- var root = chain.shift();
51
-
52
- var obj;
53
- if (root === '[]' && options.parseArrays) {
54
- obj = [];
55
- obj = obj.concat(parseObject(chain, val, options));
56
- } else {
57
- obj = options.plainObjects ? Object.create(null) : {};
58
- var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
59
- var index = parseInt(cleanRoot, 10);
60
- if (!options.parseArrays && cleanRoot === '') {
61
- obj = { 0: val };
62
- } else if (
63
- !isNaN(index)
64
- && root !== cleanRoot
65
- && String(index) === cleanRoot
66
- && index >= 0
67
- && (options.parseArrays && index <= options.arrayLimit)
68
- ) {
52
+ for (var i = chain.length - 1; i >= 0; --i) {
53
+ var obj;
54
+ var root = chain[i];
55
+
56
+ if (root === '[]') {
69
57
  obj = [];
70
- obj[index] = parseObject(chain, val, options);
71
- } else if (cleanRoot !== '__proto__') {
72
- obj[cleanRoot] = parseObject(chain, val, options);
58
+ obj = obj.concat(leaf);
59
+ } else {
60
+ obj = options.plainObjects ? Object.create(null) : {};
61
+ var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
62
+ var index = parseInt(cleanRoot, 10);
63
+ if (
64
+ !isNaN(index)
65
+ && root !== cleanRoot
66
+ && String(index) === cleanRoot
67
+ && index >= 0
68
+ && (options.parseArrays && index <= options.arrayLimit)
69
+ ) {
70
+ obj = [];
71
+ obj[index] = leaf;
72
+ } else {
73
+ obj[cleanRoot] = leaf;
74
+ }
73
75
  }
76
+
77
+ leaf = obj;
74
78
  }
75
79
 
76
- return obj;
80
+ return leaf;
77
81
  };
78
82
 
79
83
  var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
@@ -98,7 +102,8 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
98
102
 
99
103
  var keys = [];
100
104
  if (parent) {
101
- // If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties
105
+ // If we aren't using plain objects, optionally prefix keys
106
+ // that would overwrite object prototype properties
102
107
  if (!options.plainObjects && has.call(Object.prototype, parent)) {
103
108
  if (!options.allowPrototypes) {
104
109
  return;
@@ -131,12 +136,13 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
131
136
  };
132
137
 
133
138
  module.exports = function (str, opts) {
134
- var options = opts || {};
139
+ var options = opts ? utils.assign({}, opts) : {};
135
140
 
136
141
  if (options.decoder !== null && options.decoder !== undefined && typeof options.decoder !== 'function') {
137
142
  throw new TypeError('Decoder has to be a function.');
138
143
  }
139
144
 
145
+ options.ignoreQueryPrefix = options.ignoreQueryPrefix === true;
140
146
  options.delimiter = typeof options.delimiter === 'string' || utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter;
141
147
  options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth;
142
148
  options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;