qs 2.2.1 → 2.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/CHANGELOG.md ADDED
@@ -0,0 +1,50 @@
1
+
2
+ ## [**2.2.4**](https://github.com/hapijs/qs/issues?milestone=13&state=closed)
3
+ - [**#38**](https://github.com/hapijs/qs/issues/38) how to handle object keys beginning with a number
4
+
5
+ ## [**2.2.3**](https://github.com/hapijs/qs/issues?milestone=12&state=closed)
6
+ - [**#37**](https://github.com/hapijs/qs/issues/37) parser discards first empty value in array
7
+ - [**#36**](https://github.com/hapijs/qs/issues/36) Update to lab 4.x
8
+
9
+ ## [**2.2.2**](https://github.com/hapijs/qs/issues?milestone=11&state=closed)
10
+ - [**#33**](https://github.com/hapijs/qs/issues/33) Error when plain object in a value
11
+ - [**#34**](https://github.com/hapijs/qs/issues/34) use Object.prototype.hasOwnProperty.call instead of obj.hasOwnProperty
12
+ - [**#24**](https://github.com/hapijs/qs/issues/24) Changelog? Semver?
13
+
14
+ ## [**2.2.1**](https://github.com/hapijs/qs/issues?milestone=10&state=closed)
15
+ - [**#32**](https://github.com/hapijs/qs/issues/32) account for circular references properly, closes #31
16
+ - [**#31**](https://github.com/hapijs/qs/issues/31) qs.parse stackoverflow on circular objects
17
+
18
+ ## [**2.2.0**](https://github.com/hapijs/qs/issues?milestone=9&state=closed)
19
+ - [**#26**](https://github.com/hapijs/qs/issues/26) Don't use Buffer global if it's not present
20
+ - [**#30**](https://github.com/hapijs/qs/issues/30) Bug when merging non-object values into arrays
21
+ - [**#29**](https://github.com/hapijs/qs/issues/29) Don't call Utils.clone at the top of Utils.merge
22
+ - [**#23**](https://github.com/hapijs/qs/issues/23) Ability to not limit parameters?
23
+
24
+ ## [**2.1.0**](https://github.com/hapijs/qs/issues?milestone=8&state=closed)
25
+ - [**#22**](https://github.com/hapijs/qs/issues/22) Enable using a RegExp as delimiter
26
+
27
+ ## [**2.0.0**](https://github.com/hapijs/qs/issues?milestone=7&state=closed)
28
+ - [**#18**](https://github.com/hapijs/qs/issues/18) Why is there arrayLimit?
29
+ - [**#20**](https://github.com/hapijs/qs/issues/20) Configurable parametersLimit
30
+ - [**#21**](https://github.com/hapijs/qs/issues/21) make all limits optional, for #18, for #20
31
+
32
+ ## [**1.2.2**](https://github.com/hapijs/qs/issues?milestone=6&state=closed)
33
+ - [**#19**](https://github.com/hapijs/qs/issues/19) Don't overwrite null values
34
+
35
+ ## [**1.2.1**](https://github.com/hapijs/qs/issues?milestone=5&state=closed)
36
+ - [**#16**](https://github.com/hapijs/qs/issues/16) ignore non-string delimiters
37
+ - [**#15**](https://github.com/hapijs/qs/issues/15) Close code block
38
+
39
+ ## [**1.2.0**](https://github.com/hapijs/qs/issues?milestone=4&state=closed)
40
+ - [**#12**](https://github.com/hapijs/qs/issues/12) Add optional delim argument
41
+ - [**#13**](https://github.com/hapijs/qs/issues/13) fix #11: flattened keys in array are now correctly parsed
42
+
43
+ ## [**1.1.0**](https://github.com/hapijs/qs/issues?milestone=3&state=closed)
44
+ - [**#7**](https://github.com/hapijs/qs/issues/7) Empty values of a POST array disappear after being submitted
45
+ - [**#9**](https://github.com/hapijs/qs/issues/9) Should not omit equals signs (=) when value is null
46
+ - [**#6**](https://github.com/hapijs/qs/issues/6) Minor grammar fix in README
47
+
48
+ ## [**1.0.2**](https://github.com/hapijs/qs/issues?milestone=2&state=closed)
49
+ - [**#5**](https://github.com/hapijs/qs/issues/5) array holes incorrectly copied into object on large index
50
+
package/lib/parse.js CHANGED
@@ -29,7 +29,7 @@ internals.parseValues = function (str, options) {
29
29
  var key = Utils.decode(part.slice(0, pos));
30
30
  var val = Utils.decode(part.slice(pos + 1));
31
31
 
32
- if (!obj[key]) {
32
+ if (!obj.hasOwnProperty(key)) {
33
33
  obj[key] = val;
34
34
  }
35
35
  else {
@@ -58,8 +58,10 @@ internals.parseObject = function (chain, val, options) {
58
58
  else {
59
59
  var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root;
60
60
  var index = parseInt(cleanRoot, 10);
61
+ var indexString = '' + index;
61
62
  if (!isNaN(index) &&
62
63
  root !== cleanRoot &&
64
+ indexString === cleanRoot &&
63
65
  index <= options.arrayLimit) {
64
66
 
65
67
  obj = [];
@@ -138,16 +140,16 @@ module.exports = function (str, options) {
138
140
  options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit;
139
141
  options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit;
140
142
 
141
- var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : Utils.clone(str);
143
+ var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str;
142
144
  var obj = {};
143
145
 
144
146
  // Iterate over the keys and setup the new object
145
- //
146
- for (var key in tempObj) {
147
- if (tempObj.hasOwnProperty(key)) {
148
- var newObj = internals.parseKeys(key, tempObj[key], options);
149
- obj = Utils.merge(obj, newObj);
150
- }
147
+
148
+ var keys = Object.keys(tempObj);
149
+ for (var i = 0, il = keys.length; i < il; ++i) {
150
+ var key = keys[i];
151
+ var newObj = internals.parseKeys(key, tempObj[key], options);
152
+ obj = Utils.merge(obj, newObj);
151
153
  }
152
154
 
153
155
  return Utils.compact(obj);
package/lib/stringify.js CHANGED
@@ -31,10 +31,14 @@ internals.stringify = function (obj, prefix) {
31
31
 
32
32
  var values = [];
33
33
 
34
- for (var key in obj) {
35
- if (obj.hasOwnProperty(key)) {
36
- values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']'));
37
- }
34
+ if (typeof obj === 'undefined') {
35
+ return values;
36
+ }
37
+
38
+ var objKeys = Object.keys(obj);
39
+ for (var i = 0, il = objKeys.length; i < il; ++i) {
40
+ var key = objKeys[i];
41
+ values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']'));
38
42
  }
39
43
 
40
44
  return values;
@@ -48,10 +52,10 @@ module.exports = function (obj, options) {
48
52
 
49
53
  var keys = [];
50
54
 
51
- for (var key in obj) {
52
- if (obj.hasOwnProperty(key)) {
53
- keys = keys.concat(internals.stringify(obj[key], key));
54
- }
55
+ var objKeys = Object.keys(obj);
56
+ for (var i = 0, il = objKeys.length; i < il; ++i) {
57
+ var key = objKeys[i];
58
+ keys = keys.concat(internals.stringify(obj[key], key));
55
59
  }
56
60
 
57
61
  return keys.join(delimiter);
package/lib/utils.js CHANGED
@@ -20,68 +20,26 @@ exports.arrayToObject = function (source) {
20
20
  };
21
21
 
22
22
 
23
- exports.clone = function (source, refs) {
24
-
25
- if (typeof source !== 'object' ||
26
- source === null) {
27
-
28
- return source;
29
- }
30
-
31
- if (exports.isBuffer(source)) {
32
- return source.toString();
33
- }
34
-
35
- refs = refs || [];
36
-
37
- var lookup = refs.indexOf(source);
38
- if (lookup !== -1) {
39
- return refs[lookup];
40
- }
41
-
42
- var copy = Array.isArray(source) ? [] : source;
43
-
44
- refs.push(source);
45
-
46
- for (var i in source) {
47
- if (source.hasOwnProperty(i)) {
48
- copy[i] = exports.clone(source[i], refs);
49
- }
50
- }
51
-
52
- return copy;
53
- };
54
-
55
-
56
23
  exports.merge = function (target, source) {
57
24
 
58
25
  if (!source) {
59
26
  return target;
60
27
  }
61
28
 
62
- if (Array.isArray(source)) {
63
- for (var i = 0, il = source.length; i < il; ++i) {
64
- if (typeof source[i] !== 'undefined') {
65
- if (typeof target[i] === 'object') {
66
- target[i] = exports.merge(target[i], source[i]);
67
- }
68
- else {
69
- target[i] = source[i];
70
- }
71
- }
72
- }
29
+ if (typeof source !== 'object') {
30
+ target.push(source);
31
+ return target;
32
+ }
73
33
 
34
+ if (typeof target !== 'object') {
35
+ target = [target].concat(source);
74
36
  return target;
75
37
  }
76
38
 
77
- if (Array.isArray(target)) {
78
- if (typeof source !== 'object') {
79
- target.push(source);
80
- return target;
81
- }
82
- else {
83
- target = exports.arrayToObject(target);
84
- }
39
+ if (Array.isArray(target) &&
40
+ !Array.isArray(source)) {
41
+
42
+ target = exports.arrayToObject(target);
85
43
  }
86
44
 
87
45
  var keys = Object.keys(source);
@@ -89,18 +47,11 @@ exports.merge = function (target, source) {
89
47
  var key = keys[k];
90
48
  var value = source[key];
91
49
 
92
- if (value &&
93
- typeof value === 'object') {
94
-
95
- if (!target[key]) {
96
- target[key] = exports.clone(value);
97
- }
98
- else {
99
- target[key] = exports.merge(target[key], value);
100
- }
50
+ if (!target[key]) {
51
+ target[key] = value;
101
52
  }
102
53
  else {
103
- target[key] = value;
54
+ target[key] = exports.merge(target[key], value);
104
55
  }
105
56
  }
106
57
 
@@ -146,10 +97,10 @@ exports.compact = function (obj, refs) {
146
97
  return compacted;
147
98
  }
148
99
 
149
- for (var key in obj) {
150
- if (obj.hasOwnProperty(key)) {
151
- obj[key] = exports.compact(obj[key], refs);
152
- }
100
+ var keys = Object.keys(obj);
101
+ for (var i = 0, il = keys.length; i < il; ++i) {
102
+ var key = keys[i];
103
+ obj[key] = exports.compact(obj[key], refs);
153
104
  }
154
105
 
155
106
  return obj;
@@ -163,10 +114,13 @@ exports.isRegExp = function (obj) {
163
114
 
164
115
  exports.isBuffer = function (obj) {
165
116
 
166
- if (typeof Buffer !== 'undefined') {
167
- return Buffer.isBuffer(obj);
168
- }
169
- else {
117
+ if (obj === null ||
118
+ typeof obj === 'undefined') {
119
+
170
120
  return false;
171
121
  }
122
+
123
+ return !!(obj.constructor &&
124
+ obj.constructor.isBuffer &&
125
+ obj.constructor.isBuffer(obj));
172
126
  };
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "qs",
3
- "version": "2.2.1",
3
+ "version": "2.2.5",
4
4
  "description": "A querystring parser that supports nesting and arrays, with a depth limit",
5
5
  "homepage": "https://github.com/hapijs/qs",
6
6
  "main": "index.js",
7
7
  "dependencies": {},
8
8
  "devDependencies": {
9
- "lab": "3.x.x"
9
+ "lab": "4.x.x"
10
10
  },
11
11
  "scripts": {
12
12
  "test": "make test-cov"
@@ -19,7 +19,6 @@
19
19
  "querystring",
20
20
  "qs"
21
21
  ],
22
- "author": "Nathan LaFreniere <quitlahok@gmail.com>",
23
22
  "licenses": [
24
23
  {
25
24
  "type": "BSD",
package/test/parse.js CHANGED
@@ -11,14 +11,13 @@ var internals = {};
11
11
 
12
12
  // Test shortcuts
13
13
 
14
+ var lab = exports.lab = Lab.script();
14
15
  var expect = Lab.expect;
15
- var before = Lab.before;
16
- var after = Lab.after;
17
- var describe = Lab.experiment;
18
- var it = Lab.test;
16
+ var describe = lab.experiment;
17
+ var it = lab.test;
19
18
 
20
19
 
21
- describe('#parse', function () {
20
+ describe('parse()', function () {
22
21
 
23
22
  it('parses a simple string', function (done) {
24
23
 
@@ -81,6 +80,17 @@ describe('#parse', function () {
81
80
  done();
82
81
  });
83
82
 
83
+ it('parses a mix of simple and explicit arrays', function (done) {
84
+
85
+ expect(Qs.parse('a=b&a[]=c')).to.deep.equal({ a: ['b', 'c'] });
86
+ expect(Qs.parse('a[]=b&a=c')).to.deep.equal({ a: ['b', 'c'] });
87
+ expect(Qs.parse('a[0]=b&a=c')).to.deep.equal({ a: ['b', 'c'] });
88
+ expect(Qs.parse('a=b&a[0]=c')).to.deep.equal({ a: ['b', 'c'] });
89
+ expect(Qs.parse('a[1]=b&a=c')).to.deep.equal({ a: ['b', 'c'] });
90
+ expect(Qs.parse('a=b&a[1]=c')).to.deep.equal({ a: ['b', 'c'] });
91
+ done();
92
+ });
93
+
84
94
  it('parses a nested array', function (done) {
85
95
 
86
96
  expect(Qs.parse('a[b][]=c&a[b][]=d')).to.deep.equal({ a: { b: ['c', 'd'] } });
@@ -103,6 +113,12 @@ describe('#parse', function () {
103
113
  done();
104
114
  });
105
115
 
116
+ it('supports keys that begin with a number', function (done) {
117
+
118
+ expect(Qs.parse('a[12b]=c')).to.deep.equal({ a: { '12b': 'c' } });
119
+ done();
120
+ });
121
+
106
122
  it('supports encoded = signs', function (done) {
107
123
 
108
124
  expect(Qs.parse('he%3Dllo=th%3Dere')).to.deep.equal({ 'he=llo': 'th=ere' });
@@ -189,6 +205,7 @@ describe('#parse', function () {
189
205
 
190
206
  expect(Qs.parse('a[]=b&a[]=&a[]=c')).to.deep.equal({ a: ['b', '', 'c'] });
191
207
  expect(Qs.parse('a[0]=b&a[1]=&a[2]=c&a[19]=')).to.deep.equal({ a: ['b', '', 'c', ''] });
208
+ expect(Qs.parse('a[]=&a[]=b&a[]=c')).to.deep.equal({ a: ['', 'b', 'c'] });
192
209
  done();
193
210
  });
194
211
 
@@ -205,10 +222,10 @@ describe('#parse', function () {
205
222
  done();
206
223
  });
207
224
 
208
- it('parses buffers to strings', function (done) {
225
+ it('parses buffers correctly', function (done) {
209
226
 
210
227
  var b = new Buffer('test');
211
- expect(Qs.parse({ a: b })).to.deep.equal({ a: b.toString() });
228
+ expect(Qs.parse({ a: b })).to.deep.equal({ a: b });
212
229
  done();
213
230
  });
214
231
 
@@ -356,4 +373,28 @@ describe('#parse', function () {
356
373
  expect(parsed.foo.baz).to.deep.equal(a);
357
374
  done();
358
375
  });
376
+
377
+ it('parses plain objects correctly', function (done) {
378
+
379
+ var a = Object.create(null);
380
+ a.b = 'c';
381
+
382
+ expect(Qs.parse(a)).to.deep.equal({ b: 'c' });
383
+ expect(Qs.parse({ a: a })).to.deep.equal({ a: { b: 'c' } });
384
+ done();
385
+ });
386
+
387
+ it('parses dates correctly', function (done) {
388
+
389
+ var now = new Date();
390
+ expect(Qs.parse({ a: now })).to.deep.equal({ a: now });
391
+ done();
392
+ });
393
+
394
+ it('parses regular expressions correctly', function (done) {
395
+
396
+ var re = /^test$/;
397
+ expect(Qs.parse({ a: re })).to.deep.equal({ a: re });
398
+ done();
399
+ });
359
400
  });
package/test/stringify.js CHANGED
@@ -11,14 +11,13 @@ var internals = {};
11
11
 
12
12
  // Test shortcuts
13
13
 
14
+ var lab = exports.lab = Lab.script();
14
15
  var expect = Lab.expect;
15
- var before = Lab.before;
16
- var after = Lab.after;
17
- var describe = Lab.experiment;
18
- var it = Lab.test;
16
+ var describe = lab.experiment;
17
+ var it = lab.test;
19
18
 
20
19
 
21
- describe('#stringify', function () {
20
+ describe('stringify()', function () {
22
21
 
23
22
  it('stringifies a querystring object', function (done) {
24
23
 
@@ -69,6 +68,25 @@ describe('#stringify', function () {
69
68
  done();
70
69
  });
71
70
 
71
+ it('stringifies an empty object', function (done) {
72
+
73
+ var obj = Object.create(null);
74
+ obj.a = 'b';
75
+ expect(Qs.stringify(obj)).to.equal('a=b');
76
+ done();
77
+ });
78
+
79
+ it('stringifies an object with an empty object as a child', function (done) {
80
+
81
+ var obj = {
82
+ a: Object.create(null)
83
+ };
84
+
85
+ obj.a.b = 'c';
86
+ expect(Qs.stringify(obj)).to.equal('a%5Bb%5D=c');
87
+ done();
88
+ });
89
+
72
90
  it('drops keys with a value of undefined', function (done) {
73
91
 
74
92
  expect(Qs.stringify({ a: undefined })).to.equal('');