qs 6.3.3 → 6.4.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/lib/parse.js CHANGED
@@ -50,25 +50,23 @@ var parseObject = function parseObjectRecursive(chain, val, options) {
50
50
  var root = chain.shift();
51
51
 
52
52
  var obj;
53
- if (root === '[]' && options.parseArrays) {
53
+ if (root === '[]') {
54
54
  obj = [];
55
55
  obj = obj.concat(parseObject(chain, val, options));
56
56
  } else {
57
57
  obj = options.plainObjects ? Object.create(null) : {};
58
58
  var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
59
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)
60
+ if (
61
+ !isNaN(index) &&
62
+ root !== cleanRoot &&
63
+ String(index) === cleanRoot &&
64
+ index >= 0 &&
65
+ (options.parseArrays && index <= options.arrayLimit)
68
66
  ) {
69
67
  obj = [];
70
68
  obj[index] = parseObject(chain, val, options);
71
- } else if (cleanRoot !== '__proto__') {
69
+ } else {
72
70
  obj[cleanRoot] = parseObject(chain, val, options);
73
71
  }
74
72
  }
@@ -98,7 +96,8 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
98
96
 
99
97
  var keys = [];
100
98
  if (parent) {
101
- // If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties
99
+ // If we aren't using plain objects, optionally prefix keys
100
+ // that would overwrite object prototype properties
102
101
  if (!options.plainObjects && has.call(Object.prototype, parent)) {
103
102
  if (!options.allowPrototypes) {
104
103
  return;
package/lib/stringify.js CHANGED
@@ -4,37 +4,32 @@ var utils = require('./utils');
4
4
  var formats = require('./formats');
5
5
 
6
6
  var arrayPrefixGenerators = {
7
- brackets: function brackets(prefix) {
7
+ brackets: function brackets(prefix) { // eslint-disable-line func-name-matching
8
8
  return prefix + '[]';
9
9
  },
10
- indices: function indices(prefix, key) {
10
+ indices: function indices(prefix, key) { // eslint-disable-line func-name-matching
11
11
  return prefix + '[' + key + ']';
12
12
  },
13
- repeat: function repeat(prefix) {
13
+ repeat: function repeat(prefix) { // eslint-disable-line func-name-matching
14
14
  return prefix;
15
15
  }
16
16
  };
17
17
 
18
- var isArray = Array.isArray;
19
- var push = Array.prototype.push;
20
- var pushToArray = function (arr, valueOrArray) {
21
- push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
22
- };
23
-
24
18
  var toISO = Date.prototype.toISOString;
25
19
 
26
20
  var defaults = {
27
21
  delimiter: '&',
28
22
  encode: true,
29
23
  encoder: utils.encode,
30
- serializeDate: function serializeDate(date) {
24
+ encodeValuesOnly: false,
25
+ serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching
31
26
  return toISO.call(date);
32
27
  },
33
28
  skipNulls: false,
34
29
  strictNullHandling: false
35
30
  };
36
31
 
37
- var stringify = function stringify(
32
+ var stringify = function stringify( // eslint-disable-line func-name-matching
38
33
  object,
39
34
  prefix,
40
35
  generateArrayPrefix,
@@ -45,18 +40,17 @@ var stringify = function stringify(
45
40
  sort,
46
41
  allowDots,
47
42
  serializeDate,
48
- formatter
43
+ formatter,
44
+ encodeValuesOnly
49
45
  ) {
50
46
  var obj = object;
51
47
  if (typeof filter === 'function') {
52
48
  obj = filter(prefix, obj);
53
49
  } else if (obj instanceof Date) {
54
50
  obj = serializeDate(obj);
55
- }
56
-
57
- if (obj === null) {
51
+ } else if (obj === null) {
58
52
  if (strictNullHandling) {
59
- return encoder ? encoder(prefix) : prefix;
53
+ return encoder && !encodeValuesOnly ? encoder(prefix) : prefix;
60
54
  }
61
55
 
62
56
  obj = '';
@@ -64,7 +58,8 @@ var stringify = function stringify(
64
58
 
65
59
  if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
66
60
  if (encoder) {
67
- return [formatter(encoder(prefix)) + '=' + formatter(encoder(obj))];
61
+ var keyValue = encodeValuesOnly ? prefix : encoder(prefix);
62
+ return [formatter(keyValue) + '=' + formatter(encoder(obj))];
68
63
  }
69
64
  return [formatter(prefix) + '=' + formatter(String(obj))];
70
65
  }
@@ -76,7 +71,7 @@ var stringify = function stringify(
76
71
  }
77
72
 
78
73
  var objKeys;
79
- if (isArray(filter)) {
74
+ if (Array.isArray(filter)) {
80
75
  objKeys = filter;
81
76
  } else {
82
77
  var keys = Object.keys(obj);
@@ -90,8 +85,8 @@ var stringify = function stringify(
90
85
  continue;
91
86
  }
92
87
 
93
- if (isArray(obj)) {
94
- pushToArray(values, stringify(
88
+ if (Array.isArray(obj)) {
89
+ values = values.concat(stringify(
95
90
  obj[key],
96
91
  generateArrayPrefix(prefix, key),
97
92
  generateArrayPrefix,
@@ -102,10 +97,11 @@ var stringify = function stringify(
102
97
  sort,
103
98
  allowDots,
104
99
  serializeDate,
105
- formatter
100
+ formatter,
101
+ encodeValuesOnly
106
102
  ));
107
103
  } else {
108
- pushToArray(values, stringify(
104
+ values = values.concat(stringify(
109
105
  obj[key],
110
106
  prefix + (allowDots ? '.' + key : '[' + key + ']'),
111
107
  generateArrayPrefix,
@@ -116,7 +112,8 @@ var stringify = function stringify(
116
112
  sort,
117
113
  allowDots,
118
114
  serializeDate,
119
- formatter
115
+ formatter,
116
+ encodeValuesOnly
120
117
  ));
121
118
  }
122
119
  }
@@ -128,7 +125,7 @@ module.exports = function (object, opts) {
128
125
  var obj = object;
129
126
  var options = opts || {};
130
127
 
131
- if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') {
128
+ if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
132
129
  throw new TypeError('Encoder has to be a function.');
133
130
  }
134
131
 
@@ -136,12 +133,13 @@ module.exports = function (object, opts) {
136
133
  var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling;
137
134
  var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : defaults.skipNulls;
138
135
  var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode;
139
- var encoder = encode ? typeof options.encoder === 'function' ? options.encoder : defaults.encoder : null;
136
+ var encoder = typeof options.encoder === 'function' ? options.encoder : defaults.encoder;
140
137
  var sort = typeof options.sort === 'function' ? options.sort : null;
141
138
  var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
142
139
  var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
140
+ var encodeValuesOnly = typeof options.encodeValuesOnly === 'boolean' ? options.encodeValuesOnly : defaults.encodeValuesOnly;
143
141
  if (typeof options.format === 'undefined') {
144
- options.format = formats['default'];
142
+ options.format = formats.default;
145
143
  } else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
146
144
  throw new TypeError('Unknown format option provided.');
147
145
  }
@@ -152,7 +150,7 @@ module.exports = function (object, opts) {
152
150
  if (typeof options.filter === 'function') {
153
151
  filter = options.filter;
154
152
  obj = filter('', obj);
155
- } else if (isArray(options.filter)) {
153
+ } else if (Array.isArray(options.filter)) {
156
154
  filter = options.filter;
157
155
  objKeys = filter;
158
156
  }
@@ -188,18 +186,20 @@ module.exports = function (object, opts) {
188
186
  if (skipNulls && obj[key] === null) {
189
187
  continue;
190
188
  }
191
- pushToArray(keys, stringify(
189
+
190
+ keys = keys.concat(stringify(
192
191
  obj[key],
193
192
  key,
194
193
  generateArrayPrefix,
195
194
  strictNullHandling,
196
195
  skipNulls,
197
- encoder,
196
+ encode ? encoder : null,
198
197
  filter,
199
198
  sort,
200
199
  allowDots,
201
200
  serializeDate,
202
- formatter
201
+ formatter,
202
+ encodeValuesOnly
203
203
  ));
204
204
  }
205
205
 
package/lib/utils.js CHANGED
@@ -30,8 +30,8 @@ exports.merge = function (target, source, options) {
30
30
  if (typeof source !== 'object') {
31
31
  if (Array.isArray(target)) {
32
32
  target.push(source);
33
- } else if (target && typeof target === 'object') {
34
- if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
33
+ } else if (typeof target === 'object') {
34
+ if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
35
35
  target[source] = true;
36
36
  }
37
37
  } else {
@@ -41,7 +41,7 @@ exports.merge = function (target, source, options) {
41
41
  return target;
42
42
  }
43
43
 
44
- if (!target || typeof target !== 'object') {
44
+ if (typeof target !== 'object') {
45
45
  return [target].concat(source);
46
46
  }
47
47
 
@@ -99,13 +99,13 @@ exports.encode = function (str) {
99
99
  var c = string.charCodeAt(i);
100
100
 
101
101
  if (
102
- c === 0x2D // -
103
- || c === 0x2E // .
104
- || c === 0x5F // _
105
- || c === 0x7E // ~
106
- || (c >= 0x30 && c <= 0x39) // 0-9
107
- || (c >= 0x41 && c <= 0x5A) // a-z
108
- || (c >= 0x61 && c <= 0x7A) // A-Z
102
+ c === 0x2D || // -
103
+ c === 0x2E || // .
104
+ c === 0x5F || // _
105
+ c === 0x7E || // ~
106
+ (c >= 0x30 && c <= 0x39) || // 0-9
107
+ (c >= 0x41 && c <= 0x5A) || // a-z
108
+ (c >= 0x61 && c <= 0x7A) // A-Z
109
109
  ) {
110
110
  out += string.charAt(i);
111
111
  continue;
@@ -128,11 +128,7 @@ exports.encode = function (str) {
128
128
 
129
129
  i += 1;
130
130
  c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
131
- /* eslint operator-linebreak: [2, "before"] */
132
- out += hexTable[0xF0 | (c >> 18)]
133
- + hexTable[0x80 | ((c >> 12) & 0x3F)]
134
- + hexTable[0x80 | ((c >> 6) & 0x3F)]
135
- + hexTable[0x80 | (c & 0x3F)];
131
+ out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]; // eslint-disable-line max-len
136
132
  }
137
133
 
138
134
  return out;
package/package.json CHANGED
@@ -1,54 +1,50 @@
1
1
  {
2
- "name": "qs",
3
- "description": "A querystring parser that supports nesting and arrays, with a depth limit",
4
- "homepage": "https://github.com/ljharb/qs",
5
- "version": "6.3.3",
6
- "repository": {
7
- "type": "git",
8
- "url": "https://github.com/ljharb/qs.git"
9
- },
10
- "main": "lib/index.js",
11
- "contributors": [
12
- {
13
- "name": "Jordan Harband",
14
- "email": "ljharb@gmail.com",
15
- "url": "http://ljharb.codes"
16
- }
17
- ],
18
- "keywords": [
19
- "querystring",
20
- "qs"
21
- ],
22
- "engines": {
23
- "node": ">=0.6"
24
- },
25
- "devDependencies": {
26
- "@ljharb/eslint-config": "^20.1.0",
27
- "aud": "^1.1.5",
28
- "browserify": "^16.5.2",
29
- "eclint": "^2.8.1",
30
- "eslint": "^8.6.0",
31
- "evalmd": "^0.0.17",
32
- "iconv-lite": "^0.4.24",
33
- "in-publish": "^2.0.1",
34
- "mkdirp": "^0.5.1",
35
- "nyc": "^10.3.2",
36
- "qs-iconv": "^1.0.4",
37
- "safe-publish-latest": "^2.0.0",
38
- "safer-buffer": "^2.1.2",
39
- "tape": "^5.4.0"
40
- },
41
- "scripts": {
42
- "prepublishOnly": "safe-publish-latest && npm run dist",
43
- "prepublish": "not-in-publish || npm run prepublishOnly",
44
- "pretest": "npm run --silent readme && npm run --silent lint",
45
- "test": "npm run --silent tests-only",
46
- "tests-only": "nyc tape 'test/**/*.js'",
47
- "posttest": "aud --production",
48
- "readme": "evalmd README.md",
49
- "postlint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git')",
50
- "lint": "eslint --ext=js,mjs .",
51
- "dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js"
52
- },
53
- "license": "BSD-3-Clause"
2
+ "name": "qs",
3
+ "description": "A querystring parser that supports nesting and arrays, with a depth limit",
4
+ "homepage": "https://github.com/ljharb/qs",
5
+ "version": "6.4.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/ljharb/qs.git"
9
+ },
10
+ "main": "lib/index.js",
11
+ "contributors": [
12
+ {
13
+ "name": "Jordan Harband",
14
+ "email": "ljharb@gmail.com",
15
+ "url": "http://ljharb.codes"
16
+ }
17
+ ],
18
+ "keywords": [
19
+ "querystring",
20
+ "qs"
21
+ ],
22
+ "engines": {
23
+ "node": ">=0.6"
24
+ },
25
+ "dependencies": {},
26
+ "devDependencies": {
27
+ "@ljharb/eslint-config": "^11.0.0",
28
+ "browserify": "^14.1.0",
29
+ "covert": "^1.1.0",
30
+ "eslint": "^3.17.0",
31
+ "evalmd": "^0.0.17",
32
+ "iconv-lite": "^0.4.15",
33
+ "mkdirp": "^0.5.1",
34
+ "parallelshell": "^2.0.0",
35
+ "qs-iconv": "^1.0.4",
36
+ "safe-publish-latest": "^1.1.1",
37
+ "tape": "^4.6.3"
38
+ },
39
+ "scripts": {
40
+ "prepublish": "safe-publish-latest && npm run dist",
41
+ "pretest": "npm run --silent readme && npm run --silent lint",
42
+ "test": "npm run --silent coverage",
43
+ "tests-only": "node test",
44
+ "readme": "evalmd README.md",
45
+ "lint": "eslint lib/*.js test/*.js",
46
+ "coverage": "covert test",
47
+ "dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js"
48
+ },
49
+ "license": "BSD-3-Clause"
54
50
  }
package/test/.eslintrc ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "rules": {
3
+ "consistent-return": 2,
4
+ "max-lines": 0,
5
+ "max-nested-callbacks": [2, 3],
6
+ "max-statements": 0,
7
+ "no-extend-native": 0,
8
+ "no-magic-numbers": 0,
9
+ "sort-keys": 0
10
+ }
11
+ }
package/test/parse.js CHANGED
@@ -3,7 +3,6 @@
3
3
  var test = require('tape');
4
4
  var qs = require('../');
5
5
  var iconv = require('iconv-lite');
6
- var SaferBuffer = require('safer-buffer').Buffer;
7
6
 
8
7
  test('parse()', function (t) {
9
8
  t.test('parses a simple string', function (st) {
@@ -231,7 +230,7 @@ test('parse()', function (t) {
231
230
  });
232
231
 
233
232
  t.test('parses buffers correctly', function (st) {
234
- var b = SaferBuffer.from('test');
233
+ var b = new Buffer('test');
235
234
  st.deepEqual(qs.parse({ a: b }), { a: b });
236
235
  st.end();
237
236
  });
@@ -256,7 +255,7 @@ test('parse()', function (t) {
256
255
  st.end();
257
256
  });
258
257
 
259
- t.test('should not throw when a native prototype has an enumerable property', function (st) {
258
+ t.test('should not throw when a native prototype has an enumerable property', { parallel: false }, function (st) {
260
259
  Object.prototype.crash = '';
261
260
  Array.prototype.crash = '';
262
261
  st.doesNotThrow(qs.parse.bind(null, 'a=b'));
@@ -301,14 +300,7 @@ test('parse()', function (t) {
301
300
  });
302
301
 
303
302
  t.test('allows disabling array parsing', function (st) {
304
- var indices = qs.parse('a[0]=b&a[1]=c', { parseArrays: false });
305
- st.deepEqual(indices, { a: { 0: 'b', 1: 'c' } });
306
- st.equal(Array.isArray(indices.a), false, 'parseArrays:false, indices case is not an array');
307
-
308
- var emptyBrackets = qs.parse('a[]=b', { parseArrays: false });
309
- st.deepEqual(emptyBrackets, { a: { 0: 'b' } });
310
- st.equal(Array.isArray(emptyBrackets.a), false, 'parseArrays:false, empty brackets case is not an array');
311
-
303
+ st.deepEqual(qs.parse('a[0]=b&a[1]=c', { parseArrays: false }), { a: { 0: 'b', 1: 'c' } });
312
304
  st.end();
313
305
  });
314
306
 
@@ -480,73 +472,13 @@ test('parse()', function (t) {
480
472
 
481
473
  st.deepEqual(
482
474
  qs.parse('a[b]=c&a=toString', { plainObjects: true }),
483
- { __proto__: null, a: { __proto__: null, b: 'c', toString: true } },
475
+ { a: { b: 'c', toString: true } },
484
476
  'can overwrite prototype with plainObjects true'
485
477
  );
486
478
 
487
479
  st.end();
488
480
  });
489
481
 
490
- t.test('dunder proto is ignored', function (st) {
491
- var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
492
- var result = qs.parse(payload, { allowPrototypes: true });
493
-
494
- st.deepEqual(
495
- result,
496
- {
497
- categories: {
498
- length: '42'
499
- }
500
- },
501
- 'silent [[Prototype]] payload'
502
- );
503
-
504
- var plainResult = qs.parse(payload, { allowPrototypes: true, plainObjects: true });
505
-
506
- st.deepEqual(
507
- plainResult,
508
- {
509
- __proto__: null,
510
- categories: {
511
- __proto__: null,
512
- length: '42'
513
- }
514
- },
515
- 'silent [[Prototype]] payload: plain objects'
516
- );
517
-
518
- var query = qs.parse('categories[__proto__]=cats&categories[__proto__]=dogs&categories[some][json]=toInject', { allowPrototypes: true });
519
-
520
- st.notOk(Array.isArray(query.categories), 'is not an array');
521
- st.notOk(query.categories instanceof Array, 'is not instanceof an array');
522
- st.deepEqual(query.categories, { some: { json: 'toInject' } });
523
- st.equal(JSON.stringify(query.categories), '{"some":{"json":"toInject"}}', 'stringifies as a non-array');
524
-
525
- st.deepEqual(
526
- qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true }),
527
- {
528
- foo: {
529
- bar: 'stuffs'
530
- }
531
- },
532
- 'hidden values'
533
- );
534
-
535
- st.deepEqual(
536
- qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true, plainObjects: true }),
537
- {
538
- __proto__: null,
539
- foo: {
540
- __proto__: null,
541
- bar: 'stuffs'
542
- }
543
- },
544
- 'hidden values: plain objects'
545
- );
546
-
547
- st.end();
548
- });
549
-
550
482
  t.test('can return null objects', { skip: !Object.create }, function (st) {
551
483
  var expected = Object.create(null);
552
484
  expected.a = Object.create(null);
@@ -572,14 +504,14 @@ test('parse()', function (t) {
572
504
  result.push(parseInt(parts[1], 16));
573
505
  parts = reg.exec(str);
574
506
  }
575
- return iconv.decode(SaferBuffer.from(result), 'shift_jis').toString();
507
+ return iconv.decode(new Buffer(result), 'shift_jis').toString();
576
508
  }
577
509
  }), { 県: '大阪府' });
578
510
  st.end();
579
511
  });
580
512
 
581
513
  t.test('throws error with wrong decoder', function (st) {
582
- st['throws'](function () {
514
+ st.throws(function () {
583
515
  qs.parse({}, { decoder: 'string' });
584
516
  }, new TypeError('Decoder has to be a function.'));
585
517
  st.end();
package/test/stringify.js CHANGED
@@ -3,7 +3,6 @@
3
3
  var test = require('tape');
4
4
  var qs = require('../');
5
5
  var iconv = require('iconv-lite');
6
- var SaferBuffer = require('safer-buffer').Buffer;
7
6
 
8
7
  test('stringify()', function (t) {
9
8
  t.test('stringifies a querystring object', function (st) {
@@ -326,8 +325,8 @@ test('stringify()', function (t) {
326
325
  });
327
326
 
328
327
  t.test('stringifies buffer values', function (st) {
329
- st.equal(qs.stringify({ a: SaferBuffer.from('test') }), 'a=test');
330
- st.equal(qs.stringify({ a: { b: SaferBuffer.from('test') } }), 'a%5Bb%5D=test');
328
+ st.equal(qs.stringify({ a: new Buffer('test') }), 'a=test');
329
+ st.equal(qs.stringify({ a: { b: new Buffer('test') } }), 'a%5Bb%5D=test');
331
330
  st.end();
332
331
  });
333
332
 
@@ -454,14 +453,14 @@ test('stringify()', function (t) {
454
453
  });
455
454
 
456
455
  t.test('throws error with wrong encoder', function (st) {
457
- st['throws'](function () {
456
+ st.throws(function () {
458
457
  qs.stringify({}, { encoder: 'string' });
459
458
  }, new TypeError('Encoder has to be a function.'));
460
459
  st.end();
461
460
  });
462
461
 
463
462
  t.test('can use custom encoder for a buffer object', { skip: typeof Buffer === 'undefined' }, function (st) {
464
- st.equal(qs.stringify({ a: SaferBuffer.from([1]) }, {
463
+ st.equal(qs.stringify({ a: new Buffer([1]) }, {
465
464
  encoder: function (buffer) {
466
465
  if (typeof buffer === 'string') {
467
466
  return buffer;
@@ -469,12 +468,6 @@ test('stringify()', function (t) {
469
468
  return String.fromCharCode(buffer.readUInt8(0) + 97);
470
469
  }
471
470
  }), 'a=b');
472
-
473
- st.equal(qs.stringify({ a: SaferBuffer.from('a b') }, {
474
- encoder: function (buffer) {
475
- return buffer;
476
- }
477
- }), 'a=a b');
478
471
  st.end();
479
472
  });
480
473
 
@@ -490,7 +483,7 @@ test('stringify()', function (t) {
490
483
  mutatedDate.toISOString = function () {
491
484
  throw new SyntaxError();
492
485
  };
493
- st['throws'](function () {
486
+ st.throws(function () {
494
487
  mutatedDate.toISOString();
495
488
  }, SyntaxError);
496
489
  st.equal(
@@ -515,54 +508,60 @@ test('stringify()', function (t) {
515
508
  t.test('RFC 1738 spaces serialization', function (st) {
516
509
  st.equal(qs.stringify({ a: 'b c' }, { format: qs.formats.RFC1738 }), 'a=b+c');
517
510
  st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC1738 }), 'a+b=c+d');
518
- st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC1738 }), 'a+b=a+b');
519
511
  st.end();
520
512
  });
521
513
 
522
514
  t.test('RFC 3986 spaces serialization', function (st) {
523
515
  st.equal(qs.stringify({ a: 'b c' }, { format: qs.formats.RFC3986 }), 'a=b%20c');
524
516
  st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC3986 }), 'a%20b=c%20d');
525
- st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC3986 }), 'a%20b=a%20b');
526
517
  st.end();
527
518
  });
528
519
 
529
520
  t.test('Backward compatibility to RFC 3986', function (st) {
530
521
  st.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
531
- st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }), 'a%20b=a%20b');
532
522
  st.end();
533
523
  });
534
524
 
535
525
  t.test('Edge cases and unknown formats', function (st) {
536
- ['UFO1234', false, 1234, null, {}, []].forEach(function (format) {
537
- st['throws'](
538
- function () {
539
- qs.stringify({ a: 'b c' }, { format: format });
540
- },
541
- new TypeError('Unknown format option provided.')
542
- );
543
- });
526
+ ['UFO1234', false, 1234, null, {}, []].forEach(
527
+ function (format) {
528
+ st.throws(
529
+ function () {
530
+ qs.stringify({ a: 'b c' }, { format: format });
531
+ },
532
+ new TypeError('Unknown format option provided.')
533
+ );
534
+ }
535
+ );
544
536
  st.end();
545
537
  });
546
538
 
547
- t.test('strictNullHandling works with custom filter', function (st) {
548
- var filter = function (prefix, value) {
549
- return value;
550
- };
551
-
552
- var options = { strictNullHandling: true, filter: filter };
553
- st.equal(qs.stringify({ key: null }, options), 'key');
539
+ t.test('encodeValuesOnly', function (st) {
540
+ st.equal(
541
+ qs.stringify(
542
+ { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] },
543
+ { encodeValuesOnly: true }
544
+ ),
545
+ 'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h'
546
+ );
547
+ st.equal(
548
+ qs.stringify(
549
+ { a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }
550
+ ),
551
+ 'a=b&c%5B0%5D=d&c%5B1%5D=e&f%5B0%5D%5B0%5D=g&f%5B1%5D%5B0%5D=h'
552
+ );
554
553
  st.end();
555
554
  });
556
555
 
557
- t.test('strictNullHandling works with null serializeDate', function (st) {
558
- var serializeDate = function () {
559
- return null;
560
- };
561
- var options = { strictNullHandling: true, serializeDate: serializeDate };
562
- var date = new Date();
563
- st.equal(qs.stringify({ key: date }, options), 'key');
556
+ t.test('encodeValuesOnly - strictNullHandling', function (st) {
557
+ st.equal(
558
+ qs.stringify(
559
+ { a: { b: null } },
560
+ { encodeValuesOnly: true, strictNullHandling: true }
561
+ ),
562
+ 'a[b]'
563
+ );
564
564
  st.end();
565
565
  });
566
566
 
567
- t.end();
568
567
  });