qs 6.5.3 → 6.6.0

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
@@ -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',
@@ -42,21 +42,62 @@ var defaults = {
42
42
  allowDots: false,
43
43
  allowPrototypes: false,
44
44
  arrayLimit: 20,
45
+ charset: 'utf-8',
46
+ charsetSentinel: false,
45
47
  decoder: utils.decode,
46
48
  delimiter: '&',
47
49
  depth: 5,
50
+ ignoreQueryPrefix: false,
51
+ interpretNumericEntities: false,
48
52
  parameterLimit: 1000,
53
+ parseArrays: true,
49
54
  plainObjects: false,
50
55
  strictNullHandling: false
51
56
  };
52
57
 
58
+ var interpretNumericEntities = function (str) {
59
+ return str.replace(/&#(\d+);/g, function ($0, numberStr) {
60
+ return String.fromCharCode(parseInt(numberStr, 10));
61
+ });
62
+ };
63
+
64
+ // This is what browsers will submit when the ✓ character occurs in an
65
+ // application/x-www-form-urlencoded body and the encoding of the page containing
66
+ // the form is iso-8859-1, or when the submitted form has an accept-charset
67
+ // attribute of iso-8859-1. Presumably also with other charsets that do not contain
68
+ // the ✓ character, such as us-ascii.
69
+ var isoSentinel = 'utf8=%26%2310003%3B'; // encodeURIComponent('✓')
70
+
71
+ // These are the percent-encoded utf-8 octets representing a checkmark, indicating that the request actually is utf-8 encoded.
72
+ var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')
73
+
53
74
  var parseValues = function parseQueryStringValues(str, options) {
54
75
  var obj = {};
55
76
  var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
56
77
  var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
57
78
  var parts = cleanStr.split(options.delimiter, limit);
79
+ var skipIndex = -1; // Keep track of where the utf8 sentinel was found
80
+ var i;
81
+
82
+ var charset = options.charset;
83
+ if (options.charsetSentinel) {
84
+ for (i = 0; i < parts.length; ++i) {
85
+ if (parts[i].indexOf('utf8=') === 0) {
86
+ if (parts[i] === charsetSentinel) {
87
+ charset = 'utf-8';
88
+ } else if (parts[i] === isoSentinel) {
89
+ charset = 'iso-8859-1';
90
+ }
91
+ skipIndex = i;
92
+ i = parts.length; // The eslint settings do not allow break;
93
+ }
94
+ }
95
+ }
58
96
 
59
- for (var i = 0; i < parts.length; ++i) {
97
+ for (i = 0; i < parts.length; ++i) {
98
+ if (i === skipIndex) {
99
+ continue;
100
+ }
60
101
  var part = parts[i];
61
102
 
62
103
  var bracketEqualsPos = part.indexOf(']=');
@@ -64,14 +105,18 @@ var parseValues = function parseQueryStringValues(str, options) {
64
105
 
65
106
  var key, val;
66
107
  if (pos === -1) {
67
- key = options.decoder(part, defaults.decoder);
108
+ key = options.decoder(part, defaults.decoder, charset);
68
109
  val = options.strictNullHandling ? null : '';
69
110
  } else {
70
- key = options.decoder(part.slice(0, pos), defaults.decoder);
71
- val = options.decoder(part.slice(pos + 1), defaults.decoder);
111
+ key = options.decoder(part.slice(0, pos), defaults.decoder, charset);
112
+ val = options.decoder(part.slice(pos + 1), defaults.decoder, charset);
113
+ }
114
+
115
+ if (val && options.interpretNumericEntities && charset === 'iso-8859-1') {
116
+ val = interpretNumericEntities(val);
72
117
  }
73
118
  if (has.call(obj, key)) {
74
- obj[key] = [].concat(obj[key]).concat(val);
119
+ obj[key] = utils.combine(obj[key], val);
75
120
  } else {
76
121
  obj[key] = val;
77
122
  }
@@ -104,7 +149,7 @@ var parseObject = function (chain, val, options) {
104
149
  ) {
105
150
  obj = [];
106
151
  obj[index] = leaf;
107
- } else if (cleanRoot !== '__proto__') {
152
+ } else {
108
153
  obj[cleanRoot] = leaf;
109
154
  }
110
155
  }
@@ -137,8 +182,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
137
182
 
138
183
  var keys = [];
139
184
  if (parent) {
140
- // If we aren't using plain objects, optionally prefix keys
141
- // that would overwrite object prototype properties
185
+ // If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties
142
186
  if (!options.plainObjects && has.call(Object.prototype, parent)) {
143
187
  if (!options.allowPrototypes) {
144
188
  return;
@@ -183,12 +227,19 @@ module.exports = function (str, opts) {
183
227
  options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;
184
228
  options.parseArrays = options.parseArrays !== false;
185
229
  options.decoder = typeof options.decoder === 'function' ? options.decoder : defaults.decoder;
186
- options.allowDots = typeof options.allowDots === 'boolean' ? options.allowDots : defaults.allowDots;
230
+ options.allowDots = typeof options.allowDots === 'undefined' ? defaults.allowDots : !!options.allowDots;
187
231
  options.plainObjects = typeof options.plainObjects === 'boolean' ? options.plainObjects : defaults.plainObjects;
188
232
  options.allowPrototypes = typeof options.allowPrototypes === 'boolean' ? options.allowPrototypes : defaults.allowPrototypes;
189
233
  options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : defaults.parameterLimit;
190
234
  options.strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling;
191
235
 
236
+ if (typeof options.charset !== 'undefined' && options.charset !== 'utf-8' && options.charset !== 'iso-8859-1') {
237
+ throw new Error('The charset option must be either utf-8, iso-8859-1, or undefined');
238
+ }
239
+ if (typeof options.charset === 'undefined') {
240
+ options.charset = defaults.charset;
241
+ }
242
+
192
243
  if (str === '' || str === null || typeof str === 'undefined') {
193
244
  return options.plainObjects ? Object.create(null) : {};
194
245
  }
@@ -215,13 +266,13 @@ var utils = require('./utils');
215
266
  var formats = require('./formats');
216
267
 
217
268
  var arrayPrefixGenerators = {
218
- brackets: function brackets(prefix) {
269
+ brackets: function brackets(prefix) { // eslint-disable-line func-name-matching
219
270
  return prefix + '[]';
220
271
  },
221
- indices: function indices(prefix, key) {
272
+ indices: function indices(prefix, key) { // eslint-disable-line func-name-matching
222
273
  return prefix + '[' + key + ']';
223
274
  },
224
- repeat: function repeat(prefix) {
275
+ repeat: function repeat(prefix) { // eslint-disable-line func-name-matching
225
276
  return prefix;
226
277
  }
227
278
  };
@@ -235,18 +286,24 @@ var pushToArray = function (arr, valueOrArray) {
235
286
  var toISO = Date.prototype.toISOString;
236
287
 
237
288
  var defaults = {
289
+ addQueryPrefix: false,
290
+ allowDots: false,
291
+ charset: 'utf-8',
292
+ charsetSentinel: false,
238
293
  delimiter: '&',
239
294
  encode: true,
240
295
  encoder: utils.encode,
241
296
  encodeValuesOnly: false,
242
- serializeDate: function serializeDate(date) {
297
+ // deprecated
298
+ indices: false,
299
+ serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching
243
300
  return toISO.call(date);
244
301
  },
245
302
  skipNulls: false,
246
303
  strictNullHandling: false
247
304
  };
248
305
 
249
- var stringify = function stringify(
306
+ var stringify = function stringify( // eslint-disable-line func-name-matching
250
307
  object,
251
308
  prefix,
252
309
  generateArrayPrefix,
@@ -258,7 +315,8 @@ var stringify = function stringify(
258
315
  allowDots,
259
316
  serializeDate,
260
317
  formatter,
261
- encodeValuesOnly
318
+ encodeValuesOnly,
319
+ charset
262
320
  ) {
263
321
  var obj = object;
264
322
  if (typeof filter === 'function') {
@@ -269,7 +327,7 @@ var stringify = function stringify(
269
327
 
270
328
  if (obj === null) {
271
329
  if (strictNullHandling) {
272
- return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder) : prefix;
330
+ return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset) : prefix;
273
331
  }
274
332
 
275
333
  obj = '';
@@ -277,8 +335,8 @@ var stringify = function stringify(
277
335
 
278
336
  if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
279
337
  if (encoder) {
280
- var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder);
281
- return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder))];
338
+ var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset);
339
+ return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset))];
282
340
  }
283
341
  return [formatter(prefix) + '=' + formatter(String(obj))];
284
342
  }
@@ -290,7 +348,7 @@ var stringify = function stringify(
290
348
  }
291
349
 
292
350
  var objKeys;
293
- if (isArray(filter)) {
351
+ if (Array.isArray(filter)) {
294
352
  objKeys = filter;
295
353
  } else {
296
354
  var keys = Object.keys(obj);
@@ -304,7 +362,7 @@ var stringify = function stringify(
304
362
  continue;
305
363
  }
306
364
 
307
- if (isArray(obj)) {
365
+ if (Array.isArray(obj)) {
308
366
  pushToArray(values, stringify(
309
367
  obj[key],
310
368
  generateArrayPrefix(prefix, key),
@@ -317,7 +375,8 @@ var stringify = function stringify(
317
375
  allowDots,
318
376
  serializeDate,
319
377
  formatter,
320
- encodeValuesOnly
378
+ encodeValuesOnly,
379
+ charset
321
380
  ));
322
381
  } else {
323
382
  pushToArray(values, stringify(
@@ -332,7 +391,8 @@ var stringify = function stringify(
332
391
  allowDots,
333
392
  serializeDate,
334
393
  formatter,
335
- encodeValuesOnly
394
+ encodeValuesOnly,
395
+ charset
336
396
  ));
337
397
  }
338
398
  }
@@ -344,7 +404,7 @@ module.exports = function (object, opts) {
344
404
  var obj = object;
345
405
  var options = opts ? utils.assign({}, opts) : {};
346
406
 
347
- if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') {
407
+ if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
348
408
  throw new TypeError('Encoder has to be a function.');
349
409
  }
350
410
 
@@ -354,9 +414,14 @@ module.exports = function (object, opts) {
354
414
  var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode;
355
415
  var encoder = typeof options.encoder === 'function' ? options.encoder : defaults.encoder;
356
416
  var sort = typeof options.sort === 'function' ? options.sort : null;
357
- var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
417
+ var allowDots = typeof options.allowDots === 'undefined' ? defaults.allowDots : !!options.allowDots;
358
418
  var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
359
419
  var encodeValuesOnly = typeof options.encodeValuesOnly === 'boolean' ? options.encodeValuesOnly : defaults.encodeValuesOnly;
420
+ var charset = options.charset || defaults.charset;
421
+ if (typeof options.charset !== 'undefined' && options.charset !== 'utf-8' && options.charset !== 'iso-8859-1') {
422
+ throw new Error('The charset option must be either utf-8, iso-8859-1, or undefined');
423
+ }
424
+
360
425
  if (typeof options.format === 'undefined') {
361
426
  options.format = formats['default'];
362
427
  } else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
@@ -369,7 +434,7 @@ module.exports = function (object, opts) {
369
434
  if (typeof options.filter === 'function') {
370
435
  filter = options.filter;
371
436
  obj = filter('', obj);
372
- } else if (isArray(options.filter)) {
437
+ } else if (Array.isArray(options.filter)) {
373
438
  filter = options.filter;
374
439
  objKeys = filter;
375
440
  }
@@ -417,13 +482,24 @@ module.exports = function (object, opts) {
417
482
  allowDots,
418
483
  serializeDate,
419
484
  formatter,
420
- encodeValuesOnly
485
+ encodeValuesOnly,
486
+ charset
421
487
  ));
422
488
  }
423
489
 
424
490
  var joined = keys.join(delimiter);
425
491
  var prefix = options.addQueryPrefix === true ? '?' : '';
426
492
 
493
+ if (options.charsetSentinel) {
494
+ if (charset === 'iso-8859-1') {
495
+ // encodeURIComponent('&#10003;'), the "numeric entity" representation of a checkmark
496
+ prefix += 'utf8=%26%2310003%3B&';
497
+ } else {
498
+ // encodeURIComponent('✓')
499
+ prefix += 'utf8=%E2%9C%93&';
500
+ }
501
+ }
502
+
427
503
  return joined.length > 0 ? prefix + joined : '';
428
504
  };
429
505
 
@@ -442,11 +518,9 @@ var hexTable = (function () {
442
518
  }());
443
519
 
444
520
  var compactQueue = function compactQueue(queue) {
445
- var obj;
446
-
447
- while (queue.length) {
521
+ while (queue.length > 1) {
448
522
  var item = queue.pop();
449
- obj = item.obj[item.prop];
523
+ var obj = item.obj[item.prop];
450
524
 
451
525
  if (Array.isArray(obj)) {
452
526
  var compacted = [];
@@ -460,8 +534,6 @@ var compactQueue = function compactQueue(queue) {
460
534
  item.obj[item.prop] = compacted;
461
535
  }
462
536
  }
463
-
464
- return obj;
465
537
  };
466
538
 
467
539
  var arrayToObject = function arrayToObject(source, options) {
@@ -483,7 +555,7 @@ var merge = function merge(target, source, options) {
483
555
  if (typeof source !== 'object') {
484
556
  if (Array.isArray(target)) {
485
557
  target.push(source);
486
- } else if (target && typeof target === 'object') {
558
+ } else if (typeof target === 'object') {
487
559
  if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
488
560
  target[source] = true;
489
561
  }
@@ -494,7 +566,7 @@ var merge = function merge(target, source, options) {
494
566
  return target;
495
567
  }
496
568
 
497
- if (!target || typeof target !== 'object') {
569
+ if (typeof target !== 'object') {
498
570
  return [target].concat(source);
499
571
  }
500
572
 
@@ -506,9 +578,8 @@ var merge = function merge(target, source, options) {
506
578
  if (Array.isArray(target) && Array.isArray(source)) {
507
579
  source.forEach(function (item, i) {
508
580
  if (has.call(target, i)) {
509
- var targetItem = target[i];
510
- if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
511
- target[i] = merge(targetItem, item, options);
581
+ if (target[i] && typeof target[i] === 'object') {
582
+ target[i] = merge(target[i], item, options);
512
583
  } else {
513
584
  target.push(item);
514
585
  }
@@ -538,15 +609,21 @@ var assign = function assignSingleSource(target, source) {
538
609
  }, target);
539
610
  };
540
611
 
541
- var decode = function (str) {
612
+ var decode = function (str, decoder, charset) {
613
+ var strWithoutPlus = str.replace(/\+/g, ' ');
614
+ if (charset === 'iso-8859-1') {
615
+ // unescape never throws, no try...catch needed:
616
+ return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape);
617
+ }
618
+ // utf-8
542
619
  try {
543
- return decodeURIComponent(str.replace(/\+/g, ' '));
620
+ return decodeURIComponent(strWithoutPlus);
544
621
  } catch (e) {
545
- return str;
622
+ return strWithoutPlus;
546
623
  }
547
624
  };
548
625
 
549
- var encode = function encode(str) {
626
+ var encode = function encode(str, defaultEncoder, charset) {
550
627
  // This code was originally written by Brian White (mscdex) for the io.js core querystring library.
551
628
  // It has been adapted here for stricter adherence to RFC 3986
552
629
  if (str.length === 0) {
@@ -555,6 +632,12 @@ var encode = function encode(str) {
555
632
 
556
633
  var string = typeof str === 'string' ? str : String(str);
557
634
 
635
+ if (charset === 'iso-8859-1') {
636
+ return escape(string).replace(/%u[0-9a-f]{4}/gi, function ($0) {
637
+ return '%26%23' + parseInt($0.slice(2), 16) + '%3B';
638
+ });
639
+ }
640
+
558
641
  var out = '';
559
642
  for (var i = 0; i < string.length; ++i) {
560
643
  var c = string.charCodeAt(i);
@@ -589,7 +672,6 @@ var encode = function encode(str) {
589
672
 
590
673
  i += 1;
591
674
  c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
592
- /* eslint operator-linebreak: [2, "before"] */
593
675
  out += hexTable[0xF0 | (c >> 18)]
594
676
  + hexTable[0x80 | ((c >> 12) & 0x3F)]
595
677
  + hexTable[0x80 | ((c >> 6) & 0x3F)]
@@ -618,7 +700,9 @@ var compact = function compact(value) {
618
700
  }
619
701
  }
620
702
 
621
- return compactQueue(queue);
703
+ compactQueue(queue);
704
+
705
+ return value;
622
706
  };
623
707
 
624
708
  var isRegExp = function isRegExp(obj) {
@@ -633,9 +717,14 @@ var isBuffer = function isBuffer(obj) {
633
717
  return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
634
718
  };
635
719
 
720
+ var combine = function combine(a, b) {
721
+ return [].concat(a, b);
722
+ };
723
+
636
724
  module.exports = {
637
725
  arrayToObject: arrayToObject,
638
726
  assign: assign,
727
+ combine: combine,
639
728
  compact: compact,
640
729
  decode: decode,
641
730
  encode: encode,
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
@@ -8,21 +8,62 @@ var defaults = {
8
8
  allowDots: false,
9
9
  allowPrototypes: false,
10
10
  arrayLimit: 20,
11
+ charset: 'utf-8',
12
+ charsetSentinel: false,
11
13
  decoder: utils.decode,
12
14
  delimiter: '&',
13
15
  depth: 5,
16
+ ignoreQueryPrefix: false,
17
+ interpretNumericEntities: false,
14
18
  parameterLimit: 1000,
19
+ parseArrays: true,
15
20
  plainObjects: false,
16
21
  strictNullHandling: false
17
22
  };
18
23
 
24
+ var interpretNumericEntities = function (str) {
25
+ return str.replace(/&#(\d+);/g, function ($0, numberStr) {
26
+ return String.fromCharCode(parseInt(numberStr, 10));
27
+ });
28
+ };
29
+
30
+ // This is what browsers will submit when the ✓ character occurs in an
31
+ // application/x-www-form-urlencoded body and the encoding of the page containing
32
+ // the form is iso-8859-1, or when the submitted form has an accept-charset
33
+ // attribute of iso-8859-1. Presumably also with other charsets that do not contain
34
+ // the ✓ character, such as us-ascii.
35
+ var isoSentinel = 'utf8=%26%2310003%3B'; // encodeURIComponent('&#10003;')
36
+
37
+ // These are the percent-encoded utf-8 octets representing a checkmark, indicating that the request actually is utf-8 encoded.
38
+ var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')
39
+
19
40
  var parseValues = function parseQueryStringValues(str, options) {
20
41
  var obj = {};
21
42
  var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
22
43
  var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
23
44
  var parts = cleanStr.split(options.delimiter, limit);
45
+ var skipIndex = -1; // Keep track of where the utf8 sentinel was found
46
+ var i;
47
+
48
+ var charset = options.charset;
49
+ if (options.charsetSentinel) {
50
+ for (i = 0; i < parts.length; ++i) {
51
+ if (parts[i].indexOf('utf8=') === 0) {
52
+ if (parts[i] === charsetSentinel) {
53
+ charset = 'utf-8';
54
+ } else if (parts[i] === isoSentinel) {
55
+ charset = 'iso-8859-1';
56
+ }
57
+ skipIndex = i;
58
+ i = parts.length; // The eslint settings do not allow break;
59
+ }
60
+ }
61
+ }
24
62
 
25
- for (var i = 0; i < parts.length; ++i) {
63
+ for (i = 0; i < parts.length; ++i) {
64
+ if (i === skipIndex) {
65
+ continue;
66
+ }
26
67
  var part = parts[i];
27
68
 
28
69
  var bracketEqualsPos = part.indexOf(']=');
@@ -30,14 +71,18 @@ var parseValues = function parseQueryStringValues(str, options) {
30
71
 
31
72
  var key, val;
32
73
  if (pos === -1) {
33
- key = options.decoder(part, defaults.decoder);
74
+ key = options.decoder(part, defaults.decoder, charset);
34
75
  val = options.strictNullHandling ? null : '';
35
76
  } else {
36
- key = options.decoder(part.slice(0, pos), defaults.decoder);
37
- val = options.decoder(part.slice(pos + 1), defaults.decoder);
77
+ key = options.decoder(part.slice(0, pos), defaults.decoder, charset);
78
+ val = options.decoder(part.slice(pos + 1), defaults.decoder, charset);
79
+ }
80
+
81
+ if (val && options.interpretNumericEntities && charset === 'iso-8859-1') {
82
+ val = interpretNumericEntities(val);
38
83
  }
39
84
  if (has.call(obj, key)) {
40
- obj[key] = [].concat(obj[key]).concat(val);
85
+ obj[key] = utils.combine(obj[key], val);
41
86
  } else {
42
87
  obj[key] = val;
43
88
  }
@@ -70,7 +115,7 @@ var parseObject = function (chain, val, options) {
70
115
  ) {
71
116
  obj = [];
72
117
  obj[index] = leaf;
73
- } else if (cleanRoot !== '__proto__') {
118
+ } else {
74
119
  obj[cleanRoot] = leaf;
75
120
  }
76
121
  }
@@ -103,8 +148,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
103
148
 
104
149
  var keys = [];
105
150
  if (parent) {
106
- // If we aren't using plain objects, optionally prefix keys
107
- // that would overwrite object prototype properties
151
+ // If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties
108
152
  if (!options.plainObjects && has.call(Object.prototype, parent)) {
109
153
  if (!options.allowPrototypes) {
110
154
  return;
@@ -149,12 +193,19 @@ module.exports = function (str, opts) {
149
193
  options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;
150
194
  options.parseArrays = options.parseArrays !== false;
151
195
  options.decoder = typeof options.decoder === 'function' ? options.decoder : defaults.decoder;
152
- options.allowDots = typeof options.allowDots === 'boolean' ? options.allowDots : defaults.allowDots;
196
+ options.allowDots = typeof options.allowDots === 'undefined' ? defaults.allowDots : !!options.allowDots;
153
197
  options.plainObjects = typeof options.plainObjects === 'boolean' ? options.plainObjects : defaults.plainObjects;
154
198
  options.allowPrototypes = typeof options.allowPrototypes === 'boolean' ? options.allowPrototypes : defaults.allowPrototypes;
155
199
  options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : defaults.parameterLimit;
156
200
  options.strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling;
157
201
 
202
+ if (typeof options.charset !== 'undefined' && options.charset !== 'utf-8' && options.charset !== 'iso-8859-1') {
203
+ throw new Error('The charset option must be either utf-8, iso-8859-1, or undefined');
204
+ }
205
+ if (typeof options.charset === 'undefined') {
206
+ options.charset = defaults.charset;
207
+ }
208
+
158
209
  if (str === '' || str === null || typeof str === 'undefined') {
159
210
  return options.plainObjects ? Object.create(null) : {};
160
211
  }