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 +50 -0
- package/lib/parse.js +10 -8
- package/lib/stringify.js +12 -8
- package/lib/utils.js +24 -70
- package/package.json +2 -3
- package/test/parse.js +48 -7
- package/test/stringify.js +23 -5
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
|
|
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) :
|
|
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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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 (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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 (
|
|
93
|
-
|
|
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
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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 (
|
|
167
|
-
|
|
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.
|
|
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": "
|
|
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
|
|
16
|
-
var
|
|
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('
|
|
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
|
|
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
|
|
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
|
|
16
|
-
var
|
|
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('
|
|
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('');
|