qs 6.2.3 → 6.2.5

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/test/parse.js CHANGED
@@ -3,10 +3,11 @@
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;
6
7
 
7
8
  test('parse()', function (t) {
8
9
  t.test('parses a simple string', function (st) {
9
- st.deepEqual(qs.parse('0=foo'), { '0': 'foo' });
10
+ st.deepEqual(qs.parse('0=foo'), { 0: 'foo' });
10
11
  st.deepEqual(qs.parse('foo=c++'), { foo: 'c ' });
11
12
  st.deepEqual(qs.parse('a[>=]=23'), { a: { '>=': '23' } });
12
13
  st.deepEqual(qs.parse('a[<=>]==23'), { a: { '<=>': '=23' } });
@@ -84,7 +85,7 @@ test('parse()', function (t) {
84
85
 
85
86
  t.test('limits specific array indices to 20', function (st) {
86
87
  st.deepEqual(qs.parse('a[20]=a'), { a: ['a'] });
87
- st.deepEqual(qs.parse('a[21]=a'), { a: { '21': 'a' } });
88
+ st.deepEqual(qs.parse('a[21]=a'), { a: { 21: 'a' } });
88
89
  st.end();
89
90
  });
90
91
 
@@ -115,11 +116,11 @@ test('parse()', function (t) {
115
116
  });
116
117
 
117
118
  t.test('transforms arrays to objects', function (st) {
118
- st.deepEqual(qs.parse('foo[0]=bar&foo[bad]=baz'), { foo: { '0': 'bar', bad: 'baz' } });
119
- st.deepEqual(qs.parse('foo[bad]=baz&foo[0]=bar'), { foo: { bad: 'baz', '0': 'bar' } });
120
- st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar'), { foo: { bad: 'baz', '0': 'bar' } });
121
- st.deepEqual(qs.parse('foo[]=bar&foo[bad]=baz'), { foo: { '0': 'bar', bad: 'baz' } });
122
- st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar&foo[]=foo'), { foo: { bad: 'baz', '0': 'bar', '1': 'foo' } });
119
+ st.deepEqual(qs.parse('foo[0]=bar&foo[bad]=baz'), { foo: { 0: 'bar', bad: 'baz' } });
120
+ st.deepEqual(qs.parse('foo[bad]=baz&foo[0]=bar'), { foo: { bad: 'baz', 0: 'bar' } });
121
+ st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar'), { foo: { bad: 'baz', 0: 'bar' } });
122
+ st.deepEqual(qs.parse('foo[]=bar&foo[bad]=baz'), { foo: { 0: 'bar', bad: 'baz' } });
123
+ st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar&foo[]=foo'), { foo: { bad: 'baz', 0: 'bar', 1: 'foo' } });
123
124
  st.deepEqual(qs.parse('foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb'), { foo: [{ a: 'a', b: 'b' }, { a: 'aa', b: 'bb' }] });
124
125
 
125
126
  st.deepEqual(qs.parse('a[]=b&a[t]=u&a[hasOwnProperty]=c', { allowPrototypes: false }), { a: { 0: 'b', t: 'u' } });
@@ -135,16 +136,16 @@ test('parse()', function (t) {
135
136
  st.deepEqual(qs.parse('foo[0][0].baz=bar&fool.bad=baz', { allowDots: true }), { foo: [[{ baz: 'bar' }]], fool: { bad: 'baz' } });
136
137
  st.deepEqual(qs.parse('foo[0].baz[0]=15&foo[0].bar=2', { allowDots: true }), { foo: [{ baz: ['15'], bar: '2' }] });
137
138
  st.deepEqual(qs.parse('foo[0].baz[0]=15&foo[0].baz[1]=16&foo[0].bar=2', { allowDots: true }), { foo: [{ baz: ['15', '16'], bar: '2' }] });
138
- st.deepEqual(qs.parse('foo.bad=baz&foo[0]=bar', { allowDots: true }), { foo: { bad: 'baz', '0': 'bar' } });
139
- st.deepEqual(qs.parse('foo.bad=baz&foo[]=bar', { allowDots: true }), { foo: { bad: 'baz', '0': 'bar' } });
140
- st.deepEqual(qs.parse('foo[]=bar&foo.bad=baz', { allowDots: true }), { foo: { '0': 'bar', bad: 'baz' } });
141
- st.deepEqual(qs.parse('foo.bad=baz&foo[]=bar&foo[]=foo', { allowDots: true }), { foo: { bad: 'baz', '0': 'bar', '1': 'foo' } });
139
+ st.deepEqual(qs.parse('foo.bad=baz&foo[0]=bar', { allowDots: true }), { foo: { bad: 'baz', 0: 'bar' } });
140
+ st.deepEqual(qs.parse('foo.bad=baz&foo[]=bar', { allowDots: true }), { foo: { bad: 'baz', 0: 'bar' } });
141
+ st.deepEqual(qs.parse('foo[]=bar&foo.bad=baz', { allowDots: true }), { foo: { 0: 'bar', bad: 'baz' } });
142
+ st.deepEqual(qs.parse('foo.bad=baz&foo[]=bar&foo[]=foo', { allowDots: true }), { foo: { bad: 'baz', 0: 'bar', 1: 'foo' } });
142
143
  st.deepEqual(qs.parse('foo[0].a=a&foo[0].b=b&foo[1].a=aa&foo[1].b=bb', { allowDots: true }), { foo: [{ a: 'a', b: 'b' }, { a: 'aa', b: 'bb' }] });
143
144
  st.end();
144
145
  });
145
146
 
146
147
  t.test('correctly prunes undefined values when converting an array to an object', function (st) {
147
- st.deepEqual(qs.parse('a[2]=b&a[99999999]=c'), { a: { '2': 'b', '99999999': 'c' } });
148
+ st.deepEqual(qs.parse('a[2]=b&a[99999999]=c'), { a: { 2: 'b', 99999999: 'c' } });
148
149
  st.end();
149
150
  });
150
151
 
@@ -156,7 +157,7 @@ test('parse()', function (t) {
156
157
  });
157
158
 
158
159
  t.test('doesn\'t produce empty keys', function (st) {
159
- st.deepEqual(qs.parse('_r=1&'), { '_r': '1' });
160
+ st.deepEqual(qs.parse('_r=1&'), { _r: '1' });
160
161
  st.end();
161
162
  });
162
163
 
@@ -221,14 +222,14 @@ test('parse()', function (t) {
221
222
  });
222
223
 
223
224
  t.test('parses buffers correctly', function (st) {
224
- var b = new Buffer('test');
225
+ var b = SaferBuffer.from('test');
225
226
  st.deepEqual(qs.parse({ a: b }), { a: b });
226
227
  st.end();
227
228
  });
228
229
 
229
230
  t.test('continues parsing when no parent is found', function (st) {
230
- st.deepEqual(qs.parse('[]=&a=b'), { '0': '', a: 'b' });
231
- st.deepEqual(qs.parse('[]&a=b', { strictNullHandling: true }), { '0': null, a: 'b' });
231
+ st.deepEqual(qs.parse('[]=&a=b'), { 0: '', a: 'b' });
232
+ st.deepEqual(qs.parse('[]&a=b', { strictNullHandling: true }), { 0: null, a: 'b' });
232
233
  st.deepEqual(qs.parse('[foo]=bar'), { foo: 'bar' });
233
234
  st.end();
234
235
  });
@@ -244,7 +245,7 @@ test('parse()', function (t) {
244
245
  st.end();
245
246
  });
246
247
 
247
- t.test('should not throw when a native prototype has an enumerable property', { parallel: false }, function (st) {
248
+ t.test('should not throw when a native prototype has an enumerable property', function (st) {
248
249
  Object.prototype.crash = '';
249
250
  Array.prototype.crash = '';
250
251
  st.doesNotThrow(qs.parse.bind(null, 'a=b'));
@@ -282,14 +283,21 @@ test('parse()', function (t) {
282
283
  });
283
284
 
284
285
  t.test('allows overriding array limit', function (st) {
285
- st.deepEqual(qs.parse('a[0]=b', { arrayLimit: -1 }), { a: { '0': 'b' } });
286
+ st.deepEqual(qs.parse('a[0]=b', { arrayLimit: -1 }), { a: { 0: 'b' } });
286
287
  st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: -1 }), { a: { '-1': 'b' } });
287
- st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayLimit: 0 }), { a: { '0': 'b', '1': 'c' } });
288
+ st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayLimit: 0 }), { a: { 0: 'b', 1: 'c' } });
288
289
  st.end();
289
290
  });
290
291
 
291
292
  t.test('allows disabling array parsing', function (st) {
292
- st.deepEqual(qs.parse('a[0]=b&a[1]=c', { parseArrays: false }), { a: { '0': 'b', '1': 'c' } });
293
+ var indices = qs.parse('a[0]=b&a[1]=c', { parseArrays: false });
294
+ st.deepEqual(indices, { a: { 0: 'b', 1: 'c' } });
295
+ st.equal(Array.isArray(indices.a), false, 'parseArrays:false, indices case is not an array');
296
+
297
+ var emptyBrackets = qs.parse('a[]=b', { parseArrays: false });
298
+ st.deepEqual(emptyBrackets, { a: { 0: 'b' } });
299
+ st.equal(Array.isArray(emptyBrackets.a), false, 'parseArrays:false, empty brackets case is not an array');
300
+
293
301
  st.end();
294
302
  });
295
303
 
@@ -333,13 +341,13 @@ test('parse()', function (t) {
333
341
 
334
342
  t.test('parses an object and not child values', function (st) {
335
343
  var input = {
336
- 'user[name]': { 'pop[bob]': { 'test': 3 } },
344
+ 'user[name]': { 'pop[bob]': { test: 3 } },
337
345
  'user[email]': null
338
346
  };
339
347
 
340
348
  var expected = {
341
349
  user: {
342
- name: { 'pop[bob]': { 'test': 3 } },
350
+ name: { 'pop[bob]': { test: 3 } },
343
351
  email: null
344
352
  }
345
353
  };
@@ -461,13 +469,73 @@ test('parse()', function (t) {
461
469
 
462
470
  st.deepEqual(
463
471
  qs.parse('a[b]=c&a=toString', { plainObjects: true }),
464
- { a: { b: 'c', toString: true } },
472
+ { __proto__: null, a: { __proto__: null, b: 'c', toString: true } },
465
473
  'can overwrite prototype with plainObjects true'
466
474
  );
467
475
 
468
476
  st.end();
469
477
  });
470
478
 
479
+ t.test('dunder proto is ignored', function (st) {
480
+ var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
481
+ var result = qs.parse(payload, { allowPrototypes: true });
482
+
483
+ st.deepEqual(
484
+ result,
485
+ {
486
+ categories: {
487
+ length: '42'
488
+ }
489
+ },
490
+ 'silent [[Prototype]] payload'
491
+ );
492
+
493
+ var plainResult = qs.parse(payload, { allowPrototypes: true, plainObjects: true });
494
+
495
+ st.deepEqual(
496
+ plainResult,
497
+ {
498
+ __proto__: null,
499
+ categories: {
500
+ __proto__: null,
501
+ length: '42'
502
+ }
503
+ },
504
+ 'silent [[Prototype]] payload: plain objects'
505
+ );
506
+
507
+ var query = qs.parse('categories[__proto__]=cats&categories[__proto__]=dogs&categories[some][json]=toInject', { allowPrototypes: true });
508
+
509
+ st.notOk(Array.isArray(query.categories), 'is not an array');
510
+ st.notOk(query.categories instanceof Array, 'is not instanceof an array');
511
+ st.deepEqual(query.categories, { some: { json: 'toInject' } });
512
+ st.equal(JSON.stringify(query.categories), '{"some":{"json":"toInject"}}', 'stringifies as a non-array');
513
+
514
+ st.deepEqual(
515
+ qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true }),
516
+ {
517
+ foo: {
518
+ bar: 'stuffs'
519
+ }
520
+ },
521
+ 'hidden values'
522
+ );
523
+
524
+ st.deepEqual(
525
+ qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true, plainObjects: true }),
526
+ {
527
+ __proto__: null,
528
+ foo: {
529
+ __proto__: null,
530
+ bar: 'stuffs'
531
+ }
532
+ },
533
+ 'hidden values: plain objects'
534
+ );
535
+
536
+ st.end();
537
+ });
538
+
471
539
  t.test('can return null objects', { skip: !Object.create }, function (st) {
472
540
  var expected = Object.create(null);
473
541
  expected.a = Object.create(null);
@@ -486,25 +554,23 @@ test('parse()', function (t) {
486
554
  t.test('can parse with custom encoding', function (st) {
487
555
  st.deepEqual(qs.parse('%8c%a7=%91%e5%8d%e3%95%7b', {
488
556
  decoder: function (str) {
489
- var reg = /\%([0-9A-F]{2})/ig;
557
+ var reg = /%([0-9A-F]{2})/ig;
490
558
  var result = [];
491
559
  var parts;
492
- var last = 0;
493
- while (parts = reg.exec(str)) {
560
+ // var last = 0;
561
+ while ((parts = reg.exec(str))) {
494
562
  result.push(parseInt(parts[1], 16));
495
- last = parts.index + parts[0].length;
563
+ // last = parts.index + parts[0].length;
496
564
  }
497
- return iconv.decode(new Buffer(result), 'shift_jis').toString();
565
+ return iconv.decode(SaferBuffer.from(result), 'shift_jis').toString();
498
566
  }
499
567
  }), { 県: '大阪府' });
500
568
  st.end();
501
569
  });
502
570
 
503
571
  t.test('throws error with wrong decoder', function (st) {
504
- st.throws(function () {
505
- qs.parse({}, {
506
- decoder: 'string'
507
- });
572
+ st['throws'](function () {
573
+ qs.parse({}, { decoder: 'string' });
508
574
  }, new TypeError('Decoder has to be a function.'));
509
575
  st.end();
510
576
  });
package/test/stringify.js CHANGED
@@ -3,6 +3,7 @@
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;
6
7
 
7
8
  test('stringify()', function (t) {
8
9
  t.test('stringifies a querystring object', function (st) {
@@ -39,7 +40,6 @@ test('stringify()', function (t) {
39
40
  st.end();
40
41
  });
41
42
 
42
-
43
43
  t.test('omits nested nulls when asked', function (st) {
44
44
  st.equal(qs.stringify({ a: { b: 'c', d: null } }, { skipNulls: true }), 'a%5Bb%5D=c');
45
45
  st.end();
@@ -194,8 +194,8 @@ test('stringify()', function (t) {
194
194
  });
195
195
 
196
196
  t.test('stringifies buffer values', function (st) {
197
- st.equal(qs.stringify({ a: new Buffer('test') }), 'a=test');
198
- st.equal(qs.stringify({ a: { b: new Buffer('test') } }), 'a%5Bb%5D=test');
197
+ st.equal(qs.stringify({ a: SaferBuffer.from('test') }), 'a=test');
198
+ st.equal(qs.stringify({ a: { b: SaferBuffer.from('test') } }), 'a%5Bb%5D=test');
199
199
  st.end();
200
200
  });
201
201
 
@@ -224,7 +224,7 @@ test('stringify()', function (t) {
224
224
  var calls = 0;
225
225
  var obj = { a: 'b', c: 'd', e: { f: new Date(1257894000000) } };
226
226
  var filterFunc = function (prefix, value) {
227
- calls++;
227
+ calls += 1;
228
228
  if (calls === 1) {
229
229
  st.equal(prefix, '', 'prefix is empty');
230
230
  st.equal(value, obj);
@@ -258,20 +258,20 @@ test('stringify()', function (t) {
258
258
 
259
259
  t.test('can sort the keys at depth 3 or more too', function (st) {
260
260
  var sort = function (a, b) { return a.localeCompare(b); };
261
- st.equal(qs.stringify({ a: 'a', z: { zj: {zjb: 'zjb', zja: 'zja'}, zi: {zib: 'zib', zia: 'zia'} }, b: 'b' }, { sort: sort, encode: false }), 'a=a&b=b&z[zi][zia]=zia&z[zi][zib]=zib&z[zj][zja]=zja&z[zj][zjb]=zjb');
262
- st.equal(qs.stringify({ a: 'a', z: { zj: {zjb: 'zjb', zja: 'zja'}, zi: {zib: 'zib', zia: 'zia'} }, b: 'b' }, { sort: null, encode: false }), 'a=a&z[zj][zjb]=zjb&z[zj][zja]=zja&z[zi][zib]=zib&z[zi][zia]=zia&b=b');
261
+ st.equal(qs.stringify({ a: 'a', z: { zj: { zjb: 'zjb', zja: 'zja' }, zi: { zib: 'zib', zia: 'zia' } }, b: 'b' }, { sort: sort, encode: false }), 'a=a&b=b&z[zi][zia]=zia&z[zi][zib]=zib&z[zj][zja]=zja&z[zj][zjb]=zjb');
262
+ st.equal(qs.stringify({ a: 'a', z: { zj: { zjb: 'zjb', zja: 'zja' }, zi: { zib: 'zib', zia: 'zia' } }, b: 'b' }, { sort: null, encode: false }), 'a=a&z[zj][zjb]=zjb&z[zj][zja]=zja&z[zi][zib]=zib&z[zi][zia]=zia&b=b');
263
263
  st.end();
264
264
  });
265
265
 
266
266
  t.test('can stringify with custom encoding', function (st) {
267
- st.equal(qs.stringify({ 県: '大阪府', '': ''}, {
267
+ st.equal(qs.stringify({ 県: '大阪府', '': '' }, {
268
268
  encoder: function (str) {
269
269
  if (str.length === 0) {
270
270
  return '';
271
271
  }
272
272
  var buf = iconv.encode(str, 'shiftjis');
273
273
  var result = [];
274
- for (var i=0; i < buf.length; ++i) {
274
+ for (var i = 0; i < buf.length; ++i) {
275
275
  result.push(buf.readUInt8(i).toString(16));
276
276
  }
277
277
  return '%' + result.join('%');
@@ -281,7 +281,7 @@ test('stringify()', function (t) {
281
281
  });
282
282
 
283
283
  t.test('throws error with wrong encoder', function (st) {
284
- st.throws(function () {
284
+ st['throws'](function () {
285
285
  qs.stringify({}, {
286
286
  encoder: 'string'
287
287
  });
@@ -289,10 +289,8 @@ test('stringify()', function (t) {
289
289
  st.end();
290
290
  });
291
291
 
292
- t.test('can use custom encoder for a buffer object', {
293
- skip: typeof Buffer === 'undefined'
294
- }, function (st) {
295
- st.equal(qs.stringify({ a: new Buffer([1]) }, {
292
+ t.test('can use custom encoder for a buffer object', { skip: typeof Buffer === 'undefined' }, function (st) {
293
+ st.equal(qs.stringify({ a: SaferBuffer.from([1]) }, {
296
294
  encoder: function (buffer) {
297
295
  if (typeof buffer === 'string') {
298
296
  return buffer;
package/test/utils.js CHANGED
@@ -4,6 +4,26 @@ var test = require('tape');
4
4
  var utils = require('../lib/utils');
5
5
 
6
6
  test('merge()', function (t) {
7
+ t.deepEqual(utils.merge(null, true), [null, true], 'merges true into null');
8
+
9
+ t.deepEqual(utils.merge(null, [42]), [null, 42], 'merges null into an array');
10
+
7
11
  t.deepEqual(utils.merge({ a: 'b' }, { a: 'c' }), { a: ['b', 'c'] }, 'merges two objects with the same key');
12
+
13
+ var oneMerged = utils.merge({ foo: 'bar' }, { foo: { first: '123' } });
14
+ t.deepEqual(oneMerged, { foo: ['bar', { first: '123' }] }, 'merges a standalone and an object into an array');
15
+
16
+ var twoMerged = utils.merge({ foo: ['bar', { first: '123' }] }, { foo: { second: '456' } });
17
+ t.deepEqual(twoMerged, { foo: { 0: 'bar', 1: { first: '123' }, second: '456' } }, 'merges a standalone and two objects into an array');
18
+
19
+ var sandwiched = utils.merge({ foo: ['bar', { first: '123', second: '456' }] }, { foo: 'baz' });
20
+ t.deepEqual(sandwiched, { foo: ['bar', { first: '123', second: '456' }, 'baz'] }, 'merges an object sandwiched by two standalones into an array');
21
+
22
+ var nestedArrays = utils.merge({ foo: ['baz'] }, { foo: ['bar', 'xyzzy'] });
23
+ t.deepEqual(nestedArrays, { foo: ['baz', 'bar', 'xyzzy'] });
24
+
25
+ var noOptionsNonObjectSource = utils.merge({ foo: 'baz' }, 'bar');
26
+ t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true });
27
+
8
28
  t.end();
9
29
  });
package/.eslintignore DELETED
@@ -1 +0,0 @@
1
- dist
package/LICENSE DELETED
@@ -1,28 +0,0 @@
1
- Copyright (c) 2014 Nathan LaFreniere and other contributors.
2
- All rights reserved.
3
-
4
- Redistribution and use in source and binary forms, with or without
5
- modification, are permitted provided that the following conditions are met:
6
- * Redistributions of source code must retain the above copyright
7
- notice, this list of conditions and the following disclaimer.
8
- * Redistributions in binary form must reproduce the above copyright
9
- notice, this list of conditions and the following disclaimer in the
10
- documentation and/or other materials provided with the distribution.
11
- * The names of any contributors may not be used to endorse or promote
12
- products derived from this software without specific prior written
13
- permission.
14
-
15
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
19
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
-
26
- * * *
27
-
28
- The complete list of contributors can be found at: https://github.com/hapijs/qs/graphs/contributors