qs 6.0.1 → 6.1.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/.eslintrc +17 -0
- package/.travis.yml +66 -5
- package/CHANGELOG.md +115 -0
- package/README.md +85 -81
- package/bower.json +0 -1
- package/component.json +1 -1
- package/dist/qs.js +98 -178
- package/lib/index.js +6 -12
- package/lib/parse.js +47 -72
- package/lib/stringify.js +43 -69
- package/lib/utils.js +48 -85
- package/package.json +26 -11
- package/test/index.js +5 -0
- package/test/parse.js +249 -336
- package/test/stringify.js +170 -202
- package/test/utils.js +5 -26
package/test/parse.js
CHANGED
|
@@ -1,480 +1,393 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
describe('parse()', () => {
|
|
25
|
-
|
|
26
|
-
it('parses a simple string', (done) => {
|
|
27
|
-
|
|
28
|
-
expect(Qs.parse('0=foo')).to.deep.equal({ '0': 'foo' });
|
|
29
|
-
expect(Qs.parse('foo=c++')).to.deep.equal({ foo: 'c ' });
|
|
30
|
-
expect(Qs.parse('a[>=]=23')).to.deep.equal({ a: { '>=': '23' } });
|
|
31
|
-
expect(Qs.parse('a[<=>]==23')).to.deep.equal({ a: { '<=>': '=23' } });
|
|
32
|
-
expect(Qs.parse('a[==]=23')).to.deep.equal({ a: { '==': '23' } });
|
|
33
|
-
expect(Qs.parse('foo', { strictNullHandling: true })).to.deep.equal({ foo: null });
|
|
34
|
-
expect(Qs.parse('foo')).to.deep.equal({ foo: '' });
|
|
35
|
-
expect(Qs.parse('foo=')).to.deep.equal({ foo: '' });
|
|
36
|
-
expect(Qs.parse('foo=bar')).to.deep.equal({ foo: 'bar' });
|
|
37
|
-
expect(Qs.parse(' foo = bar = baz ')).to.deep.equal({ ' foo ': ' bar = baz ' });
|
|
38
|
-
expect(Qs.parse('foo=bar=baz')).to.deep.equal({ foo: 'bar=baz' });
|
|
39
|
-
expect(Qs.parse('foo=bar&bar=baz')).to.deep.equal({ foo: 'bar', bar: 'baz' });
|
|
40
|
-
expect(Qs.parse('foo2=bar2&baz2=')).to.deep.equal({ foo2: 'bar2', baz2: '' });
|
|
41
|
-
expect(Qs.parse('foo=bar&baz', { strictNullHandling: true })).to.deep.equal({ foo: 'bar', baz: null });
|
|
42
|
-
expect(Qs.parse('foo=bar&baz')).to.deep.equal({ foo: 'bar', baz: '' });
|
|
43
|
-
expect(Qs.parse('cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World')).to.deep.equal({
|
|
3
|
+
var test = require('tape');
|
|
4
|
+
var qs = require('../');
|
|
5
|
+
|
|
6
|
+
test('parse()', function (t) {
|
|
7
|
+
t.test('parses a simple string', function (st) {
|
|
8
|
+
st.deepEqual(qs.parse('0=foo'), { '0': 'foo' });
|
|
9
|
+
st.deepEqual(qs.parse('foo=c++'), { foo: 'c ' });
|
|
10
|
+
st.deepEqual(qs.parse('a[>=]=23'), { a: { '>=': '23' } });
|
|
11
|
+
st.deepEqual(qs.parse('a[<=>]==23'), { a: { '<=>': '=23' } });
|
|
12
|
+
st.deepEqual(qs.parse('a[==]=23'), { a: { '==': '23' } });
|
|
13
|
+
st.deepEqual(qs.parse('foo', { strictNullHandling: true }), { foo: null });
|
|
14
|
+
st.deepEqual(qs.parse('foo'), { foo: '' });
|
|
15
|
+
st.deepEqual(qs.parse('foo='), { foo: '' });
|
|
16
|
+
st.deepEqual(qs.parse('foo=bar'), { foo: 'bar' });
|
|
17
|
+
st.deepEqual(qs.parse(' foo = bar = baz '), { ' foo ': ' bar = baz ' });
|
|
18
|
+
st.deepEqual(qs.parse('foo=bar=baz'), { foo: 'bar=baz' });
|
|
19
|
+
st.deepEqual(qs.parse('foo=bar&bar=baz'), { foo: 'bar', bar: 'baz' });
|
|
20
|
+
st.deepEqual(qs.parse('foo2=bar2&baz2='), { foo2: 'bar2', baz2: '' });
|
|
21
|
+
st.deepEqual(qs.parse('foo=bar&baz', { strictNullHandling: true }), { foo: 'bar', baz: null });
|
|
22
|
+
st.deepEqual(qs.parse('foo=bar&baz'), { foo: 'bar', baz: '' });
|
|
23
|
+
st.deepEqual(qs.parse('cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World'), {
|
|
44
24
|
cht: 'p3',
|
|
45
25
|
chd: 't:60,40',
|
|
46
26
|
chs: '250x100',
|
|
47
27
|
chl: 'Hello|World'
|
|
48
28
|
});
|
|
49
|
-
|
|
29
|
+
st.end();
|
|
50
30
|
});
|
|
51
31
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
done();
|
|
32
|
+
t.test('allows enabling dot notation', function (st) {
|
|
33
|
+
st.deepEqual(qs.parse('a.b=c'), { 'a.b': 'c' });
|
|
34
|
+
st.deepEqual(qs.parse('a.b=c', { allowDots: true }), { a: { b: 'c' } });
|
|
35
|
+
st.end();
|
|
57
36
|
});
|
|
58
37
|
|
|
59
|
-
|
|
38
|
+
t.deepEqual(qs.parse('a[b]=c'), { a: { b: 'c' } }, 'parses a single nested string');
|
|
39
|
+
t.deepEqual(qs.parse('a[b][c]=d'), { a: { b: { c: 'd' } } }, 'parses a double nested string');
|
|
40
|
+
t.deepEqual(
|
|
41
|
+
qs.parse('a[b][c][d][e][f][g][h]=i'),
|
|
42
|
+
{ a: { b: { c: { d: { e: { f: { '[g][h]': 'i' } } } } } } },
|
|
43
|
+
'defaults to a depth of 5'
|
|
44
|
+
);
|
|
60
45
|
|
|
61
|
-
|
|
62
|
-
|
|
46
|
+
t.test('only parses one level when depth = 1', function (st) {
|
|
47
|
+
st.deepEqual(qs.parse('a[b][c]=d', { depth: 1 }), { a: { b: { '[c]': 'd' } } });
|
|
48
|
+
st.deepEqual(qs.parse('a[b][c][d]=e', { depth: 1 }), { a: { b: { '[c][d]': 'e' } } });
|
|
49
|
+
st.end();
|
|
63
50
|
});
|
|
64
51
|
|
|
65
|
-
|
|
52
|
+
t.deepEqual(qs.parse('a=b&a=c'), { a: ['b', 'c'] }, 'parses a simple array');
|
|
66
53
|
|
|
67
|
-
|
|
68
|
-
|
|
54
|
+
t.test('parses an explicit array', function (st) {
|
|
55
|
+
st.deepEqual(qs.parse('a[]=b'), { a: ['b'] });
|
|
56
|
+
st.deepEqual(qs.parse('a[]=b&a[]=c'), { a: ['b', 'c'] });
|
|
57
|
+
st.deepEqual(qs.parse('a[]=b&a[]=c&a[]=d'), { a: ['b', 'c', 'd'] });
|
|
58
|
+
st.end();
|
|
69
59
|
});
|
|
70
60
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
t.test('parses a mix of simple and explicit arrays', function (st) {
|
|
62
|
+
st.deepEqual(qs.parse('a=b&a[]=c'), { a: ['b', 'c'] });
|
|
63
|
+
st.deepEqual(qs.parse('a[]=b&a=c'), { a: ['b', 'c'] });
|
|
64
|
+
st.deepEqual(qs.parse('a[0]=b&a=c'), { a: ['b', 'c'] });
|
|
65
|
+
st.deepEqual(qs.parse('a=b&a[0]=c'), { a: ['b', 'c'] });
|
|
66
|
+
st.deepEqual(qs.parse('a[1]=b&a=c'), { a: ['b', 'c'] });
|
|
67
|
+
st.deepEqual(qs.parse('a=b&a[1]=c'), { a: ['b', 'c'] });
|
|
68
|
+
st.end();
|
|
75
69
|
});
|
|
76
70
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
done();
|
|
71
|
+
t.test('parses a nested array', function (st) {
|
|
72
|
+
st.deepEqual(qs.parse('a[b][]=c&a[b][]=d'), { a: { b: ['c', 'd'] } });
|
|
73
|
+
st.deepEqual(qs.parse('a[>=]=25'), { a: { '>=': '25' } });
|
|
74
|
+
st.end();
|
|
82
75
|
});
|
|
83
76
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
77
|
+
t.test('allows to specify array indices', function (st) {
|
|
78
|
+
st.deepEqual(qs.parse('a[1]=c&a[0]=b&a[2]=d'), { a: ['b', 'c', 'd'] });
|
|
79
|
+
st.deepEqual(qs.parse('a[1]=c&a[0]=b'), { a: ['b', 'c'] });
|
|
80
|
+
st.deepEqual(qs.parse('a[1]=c'), { a: ['c'] });
|
|
81
|
+
st.end();
|
|
88
82
|
});
|
|
89
83
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
expect(Qs.parse('a[]=b&a[]=c&a[]=d')).to.deep.equal({ a: ['b', 'c', 'd'] });
|
|
95
|
-
done();
|
|
84
|
+
t.test('limits specific array indices to 20', function (st) {
|
|
85
|
+
st.deepEqual(qs.parse('a[20]=a'), { a: ['a'] });
|
|
86
|
+
st.deepEqual(qs.parse('a[21]=a'), { a: { '21': 'a' } });
|
|
87
|
+
st.end();
|
|
96
88
|
});
|
|
97
89
|
|
|
98
|
-
|
|
90
|
+
t.deepEqual(qs.parse('a[12b]=c'), { a: { '12b': 'c' } }, 'supports keys that begin with a number');
|
|
99
91
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
expect(Qs.parse('a=b&a[0]=c')).to.deep.equal({ a: ['b', 'c'] });
|
|
104
|
-
expect(Qs.parse('a[1]=b&a=c')).to.deep.equal({ a: ['b', 'c'] });
|
|
105
|
-
expect(Qs.parse('a=b&a[1]=c')).to.deep.equal({ a: ['b', 'c'] });
|
|
106
|
-
done();
|
|
92
|
+
t.test('supports encoded = signs', function (st) {
|
|
93
|
+
st.deepEqual(qs.parse('he%3Dllo=th%3Dere'), { 'he=llo': 'th=ere' });
|
|
94
|
+
st.end();
|
|
107
95
|
});
|
|
108
96
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
done();
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('allows to specify array indices', (done) => {
|
|
117
|
-
|
|
118
|
-
expect(Qs.parse('a[1]=c&a[0]=b&a[2]=d')).to.deep.equal({ a: ['b', 'c', 'd'] });
|
|
119
|
-
expect(Qs.parse('a[1]=c&a[0]=b')).to.deep.equal({ a: ['b', 'c'] });
|
|
120
|
-
expect(Qs.parse('a[1]=c')).to.deep.equal({ a: ['c'] });
|
|
121
|
-
done();
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('limits specific array indices to 20', (done) => {
|
|
125
|
-
|
|
126
|
-
expect(Qs.parse('a[20]=a')).to.deep.equal({ a: ['a'] });
|
|
127
|
-
expect(Qs.parse('a[21]=a')).to.deep.equal({ a: { '21': 'a' } });
|
|
128
|
-
done();
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('supports keys that begin with a number', (done) => {
|
|
132
|
-
|
|
133
|
-
expect(Qs.parse('a[12b]=c')).to.deep.equal({ a: { '12b': 'c' } });
|
|
134
|
-
done();
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('supports encoded = signs', (done) => {
|
|
138
|
-
|
|
139
|
-
expect(Qs.parse('he%3Dllo=th%3Dere')).to.deep.equal({ 'he=llo': 'th=ere' });
|
|
140
|
-
done();
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('is ok with url encoded strings', (done) => {
|
|
144
|
-
|
|
145
|
-
expect(Qs.parse('a[b%20c]=d')).to.deep.equal({ a: { 'b c': 'd' } });
|
|
146
|
-
expect(Qs.parse('a[b]=c%20d')).to.deep.equal({ a: { b: 'c d' } });
|
|
147
|
-
done();
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('allows brackets in the value', (done) => {
|
|
151
|
-
|
|
152
|
-
expect(Qs.parse('pets=["tobi"]')).to.deep.equal({ pets: '["tobi"]' });
|
|
153
|
-
expect(Qs.parse('operators=[">=", "<="]')).to.deep.equal({ operators: '[">=", "<="]' });
|
|
154
|
-
done();
|
|
97
|
+
t.test('is ok with url encoded strings', function (st) {
|
|
98
|
+
st.deepEqual(qs.parse('a[b%20c]=d'), { a: { 'b c': 'd' } });
|
|
99
|
+
st.deepEqual(qs.parse('a[b]=c%20d'), { a: { b: 'c d' } });
|
|
100
|
+
st.end();
|
|
155
101
|
});
|
|
156
102
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
expect(Qs.parse(undefined)).to.deep.equal({});
|
|
162
|
-
done();
|
|
103
|
+
t.test('allows brackets in the value', function (st) {
|
|
104
|
+
st.deepEqual(qs.parse('pets=["tobi"]'), { pets: '["tobi"]' });
|
|
105
|
+
st.deepEqual(qs.parse('operators=[">=", "<="]'), { operators: '[">=", "<="]' });
|
|
106
|
+
st.end();
|
|
163
107
|
});
|
|
164
108
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
expect(Qs.parse('foo[]=bar&foo[bad]=baz')).to.deep.equal({ foo: { '0': 'bar', bad: 'baz' } });
|
|
171
|
-
expect(Qs.parse('foo[bad]=baz&foo[]=bar&foo[]=foo')).to.deep.equal({ foo: { bad: 'baz', '0': 'bar', '1': 'foo' } });
|
|
172
|
-
expect(Qs.parse('foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb')).to.deep.equal({ foo: [{ a: 'a', b: 'b' }, { a: 'aa', b: 'bb' }] });
|
|
173
|
-
expect(Qs.parse('a[]=b&a[t]=u&a[hasOwnProperty]=c')).to.deep.equal({ a: { '0': 'b', t: 'u', c: true } });
|
|
174
|
-
expect(Qs.parse('a[]=b&a[hasOwnProperty]=c&a[x]=y')).to.deep.equal({ a: { '0': 'b', '1': 'c', x: 'y' } });
|
|
175
|
-
done();
|
|
109
|
+
t.test('allows empty values', function (st) {
|
|
110
|
+
st.deepEqual(qs.parse(''), {});
|
|
111
|
+
st.deepEqual(qs.parse(null), {});
|
|
112
|
+
st.deepEqual(qs.parse(undefined), {});
|
|
113
|
+
st.end();
|
|
176
114
|
});
|
|
177
115
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
expect(Qs.parse('foo.bad=baz&foo[]=bar&foo[]=foo', { allowDots: true })).to.deep.equal({ foo: { bad: 'baz', '0': 'bar', '1': 'foo' } });
|
|
189
|
-
expect(Qs.parse('foo[0].a=a&foo[0].b=b&foo[1].a=aa&foo[1].b=bb', { allowDots: true })).to.deep.equal({ foo: [{ a: 'a', b: 'b' }, { a: 'aa', b: 'bb' }] });
|
|
190
|
-
done();
|
|
116
|
+
t.test('transforms arrays to objects', function (st) {
|
|
117
|
+
st.deepEqual(qs.parse('foo[0]=bar&foo[bad]=baz'), { foo: { '0': 'bar', bad: 'baz' } });
|
|
118
|
+
st.deepEqual(qs.parse('foo[bad]=baz&foo[0]=bar'), { foo: { bad: 'baz', '0': 'bar' } });
|
|
119
|
+
st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar'), { foo: { bad: 'baz', '0': 'bar' } });
|
|
120
|
+
st.deepEqual(qs.parse('foo[]=bar&foo[bad]=baz'), { foo: { '0': 'bar', bad: 'baz' } });
|
|
121
|
+
st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar&foo[]=foo'), { foo: { bad: 'baz', '0': 'bar', '1': 'foo' } });
|
|
122
|
+
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' }] });
|
|
123
|
+
st.deepEqual(qs.parse('a[]=b&a[t]=u&a[hasOwnProperty]=c'), { a: { '0': 'b', t: 'u', c: true } });
|
|
124
|
+
st.deepEqual(qs.parse('a[]=b&a[hasOwnProperty]=c&a[x]=y'), { a: { '0': 'b', '1': 'c', x: 'y' } });
|
|
125
|
+
st.end();
|
|
191
126
|
});
|
|
192
127
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
128
|
+
t.test('transforms arrays to objects (dot notation)', function (st) {
|
|
129
|
+
st.deepEqual(qs.parse('foo[0].baz=bar&fool.bad=baz', { allowDots: true }), { foo: [{ baz: 'bar' }], fool: { bad: 'baz' } });
|
|
130
|
+
st.deepEqual(qs.parse('foo[0].baz=bar&fool.bad.boo=baz', { allowDots: true }), { foo: [{ baz: 'bar' }], fool: { bad: { boo: 'baz' } } });
|
|
131
|
+
st.deepEqual(qs.parse('foo[0][0].baz=bar&fool.bad=baz', { allowDots: true }), { foo: [[{ baz: 'bar' }]], fool: { bad: 'baz' } });
|
|
132
|
+
st.deepEqual(qs.parse('foo[0].baz[0]=15&foo[0].bar=2', { allowDots: true }), { foo: [{ baz: ['15'], bar: '2' }] });
|
|
133
|
+
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' }] });
|
|
134
|
+
st.deepEqual(qs.parse('foo.bad=baz&foo[0]=bar', { allowDots: true }), { foo: { bad: 'baz', '0': 'bar' } });
|
|
135
|
+
st.deepEqual(qs.parse('foo.bad=baz&foo[]=bar', { allowDots: true }), { foo: { bad: 'baz', '0': 'bar' } });
|
|
136
|
+
st.deepEqual(qs.parse('foo[]=bar&foo.bad=baz', { allowDots: true }), { foo: { '0': 'bar', bad: 'baz' } });
|
|
137
|
+
st.deepEqual(qs.parse('foo.bad=baz&foo[]=bar&foo[]=foo', { allowDots: true }), { foo: { bad: 'baz', '0': 'bar', '1': 'foo' } });
|
|
138
|
+
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' }] });
|
|
139
|
+
st.end();
|
|
197
140
|
});
|
|
198
141
|
|
|
199
|
-
|
|
142
|
+
t.deepEqual(qs.parse('a[b]=c&a=d'), { a: { b: 'c', d: true } }, 'can add keys to objects');
|
|
200
143
|
|
|
201
|
-
|
|
202
|
-
|
|
144
|
+
t.test('correctly prunes undefined values when converting an array to an object', function (st) {
|
|
145
|
+
st.deepEqual(qs.parse('a[2]=b&a[99999999]=c'), { a: { '2': 'b', '99999999': 'c' } });
|
|
146
|
+
st.end();
|
|
203
147
|
});
|
|
204
148
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
done();
|
|
149
|
+
t.test('supports malformed uri characters', function (st) {
|
|
150
|
+
st.deepEqual(qs.parse('{%:%}', { strictNullHandling: true }), { '{%:%}': null });
|
|
151
|
+
st.deepEqual(qs.parse('{%:%}='), { '{%:%}': '' });
|
|
152
|
+
st.deepEqual(qs.parse('foo=%:%}'), { foo: '%:%}' });
|
|
153
|
+
st.end();
|
|
211
154
|
});
|
|
212
155
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
done();
|
|
156
|
+
t.test('doesn\'t produce empty keys', function (st) {
|
|
157
|
+
st.deepEqual(qs.parse('_r=1&'), { '_r': '1' });
|
|
158
|
+
st.end();
|
|
217
159
|
});
|
|
218
160
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
done();
|
|
161
|
+
t.test('cannot access Object prototype', function (st) {
|
|
162
|
+
qs.parse('constructor[prototype][bad]=bad');
|
|
163
|
+
qs.parse('bad[constructor][prototype][bad]=bad');
|
|
164
|
+
st.equal(typeof Object.prototype.bad, 'undefined');
|
|
165
|
+
st.end();
|
|
225
166
|
});
|
|
226
167
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
done();
|
|
168
|
+
t.test('parses arrays of objects', function (st) {
|
|
169
|
+
st.deepEqual(qs.parse('a[][b]=c'), { a: [{ b: 'c' }] });
|
|
170
|
+
st.deepEqual(qs.parse('a[0][b]=c'), { a: [{ b: 'c' }] });
|
|
171
|
+
st.end();
|
|
232
172
|
});
|
|
233
173
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
done();
|
|
174
|
+
t.test('allows for empty strings in arrays', function (st) {
|
|
175
|
+
st.deepEqual(qs.parse('a[]=b&a[]=&a[]=c'), { a: ['b', '', 'c'] });
|
|
176
|
+
st.deepEqual(qs.parse('a[0]=b&a[1]&a[2]=c&a[19]=', { strictNullHandling: true }), { a: ['b', null, 'c', ''] });
|
|
177
|
+
st.deepEqual(qs.parse('a[0]=b&a[1]=&a[2]=c&a[19]', { strictNullHandling: true }), { a: ['b', '', 'c', null] });
|
|
178
|
+
st.deepEqual(qs.parse('a[]=&a[]=b&a[]=c'), { a: ['', 'b', 'c'] });
|
|
179
|
+
st.end();
|
|
241
180
|
});
|
|
242
181
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
done();
|
|
182
|
+
t.test('compacts sparse arrays', function (st) {
|
|
183
|
+
st.deepEqual(qs.parse('a[10]=1&a[2]=2'), { a: ['2', '1'] });
|
|
184
|
+
st.end();
|
|
247
185
|
});
|
|
248
186
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
done();
|
|
187
|
+
t.test('parses semi-parsed strings', function (st) {
|
|
188
|
+
st.deepEqual(qs.parse({ 'a[b]': 'c' }), { a: { b: 'c' } });
|
|
189
|
+
st.deepEqual(qs.parse({ 'a[b]': 'c', 'a[d]': 'e' }), { a: { b: 'c', d: 'e' } });
|
|
190
|
+
st.end();
|
|
254
191
|
});
|
|
255
192
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
done();
|
|
193
|
+
t.test('parses buffers correctly', function (st) {
|
|
194
|
+
var b = new Buffer('test');
|
|
195
|
+
st.deepEqual(qs.parse({ a: b }), { a: b });
|
|
196
|
+
st.end();
|
|
261
197
|
});
|
|
262
198
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
done();
|
|
199
|
+
t.test('continues parsing when no parent is found', function (st) {
|
|
200
|
+
st.deepEqual(qs.parse('[]=&a=b'), { '0': '', a: 'b' });
|
|
201
|
+
st.deepEqual(qs.parse('[]&a=b', { strictNullHandling: true }), { '0': null, a: 'b' });
|
|
202
|
+
st.deepEqual(qs.parse('[foo]=bar'), { foo: 'bar' });
|
|
203
|
+
st.end();
|
|
269
204
|
});
|
|
270
205
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
let str = 'a[]=a';
|
|
206
|
+
t.test('does not error when parsing a very long array', function (st) {
|
|
207
|
+
var str = 'a[]=a';
|
|
274
208
|
while (Buffer.byteLength(str) < 128 * 1024) {
|
|
275
209
|
str = str + '&' + str;
|
|
276
210
|
}
|
|
277
211
|
|
|
278
|
-
|
|
212
|
+
st.doesNotThrow(function () { qs.parse(str); });
|
|
279
213
|
|
|
280
|
-
|
|
281
|
-
}).to.not.throw();
|
|
282
|
-
|
|
283
|
-
done();
|
|
214
|
+
st.end();
|
|
284
215
|
});
|
|
285
216
|
|
|
286
|
-
|
|
287
|
-
|
|
217
|
+
t.test('should not throw when a native prototype has an enumerable property', { parallel: false }, function (st) {
|
|
288
218
|
Object.prototype.crash = '';
|
|
289
219
|
Array.prototype.crash = '';
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
220
|
+
st.doesNotThrow(qs.parse.bind(null, 'a=b'));
|
|
221
|
+
st.deepEqual(qs.parse('a=b'), { a: 'b' });
|
|
222
|
+
st.doesNotThrow(qs.parse.bind(null, 'a[][b]=c'));
|
|
223
|
+
st.deepEqual(qs.parse('a[][b]=c'), { a: [{ b: 'c' }] });
|
|
294
224
|
delete Object.prototype.crash;
|
|
295
225
|
delete Array.prototype.crash;
|
|
296
|
-
|
|
226
|
+
st.end();
|
|
297
227
|
});
|
|
298
228
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
done();
|
|
229
|
+
t.test('parses a string with an alternative string delimiter', function (st) {
|
|
230
|
+
st.deepEqual(qs.parse('a=b;c=d', { delimiter: ';' }), { a: 'b', c: 'd' });
|
|
231
|
+
st.end();
|
|
303
232
|
});
|
|
304
233
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
done();
|
|
234
|
+
t.test('parses a string with an alternative RegExp delimiter', function (st) {
|
|
235
|
+
st.deepEqual(qs.parse('a=b; c=d', { delimiter: /[;,] */ }), { a: 'b', c: 'd' });
|
|
236
|
+
st.end();
|
|
309
237
|
});
|
|
310
238
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
done();
|
|
239
|
+
t.test('does not use non-splittable objects as delimiters', function (st) {
|
|
240
|
+
st.deepEqual(qs.parse('a=b&c=d', { delimiter: true }), { a: 'b', c: 'd' });
|
|
241
|
+
st.end();
|
|
315
242
|
});
|
|
316
243
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
done();
|
|
244
|
+
t.test('allows overriding parameter limit', function (st) {
|
|
245
|
+
st.deepEqual(qs.parse('a=b&c=d', { parameterLimit: 1 }), { a: 'b' });
|
|
246
|
+
st.end();
|
|
321
247
|
});
|
|
322
248
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
done();
|
|
249
|
+
t.test('allows setting the parameter limit to Infinity', function (st) {
|
|
250
|
+
st.deepEqual(qs.parse('a=b&c=d', { parameterLimit: Infinity }), { a: 'b', c: 'd' });
|
|
251
|
+
st.end();
|
|
327
252
|
});
|
|
328
253
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
done();
|
|
254
|
+
t.test('allows overriding array limit', function (st) {
|
|
255
|
+
st.deepEqual(qs.parse('a[0]=b', { arrayLimit: -1 }), { a: { '0': 'b' } });
|
|
256
|
+
st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: -1 }), { a: { '-1': 'b' } });
|
|
257
|
+
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayLimit: 0 }), { a: { '0': 'b', '1': 'c' } });
|
|
258
|
+
st.end();
|
|
335
259
|
});
|
|
336
260
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
done();
|
|
261
|
+
t.test('allows disabling array parsing', function (st) {
|
|
262
|
+
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { parseArrays: false }), { a: { '0': 'b', '1': 'c' } });
|
|
263
|
+
st.end();
|
|
341
264
|
});
|
|
342
265
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
const input = {
|
|
266
|
+
t.test('parses an object', function (st) {
|
|
267
|
+
var input = {
|
|
346
268
|
'user[name]': { 'pop[bob]': 3 },
|
|
347
269
|
'user[email]': null
|
|
348
270
|
};
|
|
349
271
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
272
|
+
var expected = {
|
|
273
|
+
user: {
|
|
274
|
+
name: { 'pop[bob]': 3 },
|
|
275
|
+
email: null
|
|
354
276
|
}
|
|
355
277
|
};
|
|
356
278
|
|
|
357
|
-
|
|
279
|
+
var result = qs.parse(input);
|
|
358
280
|
|
|
359
|
-
|
|
360
|
-
|
|
281
|
+
st.deepEqual(result, expected);
|
|
282
|
+
st.end();
|
|
361
283
|
});
|
|
362
284
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
const input = {
|
|
285
|
+
t.test('parses an object in dot notation', function (st) {
|
|
286
|
+
var input = {
|
|
366
287
|
'user.name': { 'pop[bob]': 3 },
|
|
367
288
|
'user.email.': null
|
|
368
289
|
};
|
|
369
290
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
291
|
+
var expected = {
|
|
292
|
+
user: {
|
|
293
|
+
name: { 'pop[bob]': 3 },
|
|
294
|
+
email: null
|
|
374
295
|
}
|
|
375
296
|
};
|
|
376
297
|
|
|
377
|
-
|
|
298
|
+
var result = qs.parse(input, { allowDots: true });
|
|
378
299
|
|
|
379
|
-
|
|
380
|
-
|
|
300
|
+
st.deepEqual(result, expected);
|
|
301
|
+
st.end();
|
|
381
302
|
});
|
|
382
303
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const input = {
|
|
304
|
+
t.test('parses an object and not child values', function (st) {
|
|
305
|
+
var input = {
|
|
386
306
|
'user[name]': { 'pop[bob]': { 'test': 3 } },
|
|
387
307
|
'user[email]': null
|
|
388
308
|
};
|
|
389
309
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
310
|
+
var expected = {
|
|
311
|
+
user: {
|
|
312
|
+
name: { 'pop[bob]': { 'test': 3 } },
|
|
313
|
+
email: null
|
|
394
314
|
}
|
|
395
315
|
};
|
|
396
316
|
|
|
397
|
-
|
|
317
|
+
var result = qs.parse(input);
|
|
398
318
|
|
|
399
|
-
|
|
400
|
-
|
|
319
|
+
st.deepEqual(result, expected);
|
|
320
|
+
st.end();
|
|
401
321
|
});
|
|
402
322
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
const tempBuffer = global.Buffer;
|
|
323
|
+
t.test('does not blow up when Buffer global is missing', function (st) {
|
|
324
|
+
var tempBuffer = global.Buffer;
|
|
406
325
|
delete global.Buffer;
|
|
407
|
-
|
|
326
|
+
var result = qs.parse('a=b&c=d');
|
|
408
327
|
global.Buffer = tempBuffer;
|
|
409
|
-
|
|
410
|
-
|
|
328
|
+
st.deepEqual(result, { a: 'b', c: 'd' });
|
|
329
|
+
st.end();
|
|
411
330
|
});
|
|
412
331
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const a = {};
|
|
332
|
+
t.test('does not crash when parsing circular references', function (st) {
|
|
333
|
+
var a = {};
|
|
416
334
|
a.b = a;
|
|
417
335
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
expect(() => {
|
|
336
|
+
var parsed;
|
|
421
337
|
|
|
422
|
-
|
|
423
|
-
|
|
338
|
+
st.doesNotThrow(function () {
|
|
339
|
+
parsed = qs.parse({ 'foo[bar]': 'baz', 'foo[baz]': a });
|
|
340
|
+
});
|
|
424
341
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
342
|
+
st.equal('foo' in parsed, true, 'parsed has "foo" property');
|
|
343
|
+
st.equal('bar' in parsed.foo, true);
|
|
344
|
+
st.equal('baz' in parsed.foo, true);
|
|
345
|
+
st.equal(parsed.foo.bar, 'baz');
|
|
346
|
+
st.deepEqual(parsed.foo.baz, a);
|
|
347
|
+
st.end();
|
|
430
348
|
});
|
|
431
349
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
const a = Object.create(null);
|
|
350
|
+
t.test('parses plain objects correctly', function (st) {
|
|
351
|
+
var a = Object.create(null);
|
|
435
352
|
a.b = 'c';
|
|
436
353
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
354
|
+
st.deepEqual(qs.parse(a), { b: 'c' });
|
|
355
|
+
var result = qs.parse({ a: a });
|
|
356
|
+
st.equal('a' in result, true, 'result has "a" property');
|
|
357
|
+
st.deepEqual(result.a, a);
|
|
358
|
+
st.end();
|
|
442
359
|
});
|
|
443
360
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
done();
|
|
361
|
+
t.test('parses dates correctly', function (st) {
|
|
362
|
+
var now = new Date();
|
|
363
|
+
st.deepEqual(qs.parse({ a: now }), { a: now });
|
|
364
|
+
st.end();
|
|
449
365
|
});
|
|
450
366
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
done();
|
|
367
|
+
t.test('parses regular expressions correctly', function (st) {
|
|
368
|
+
var re = /^test$/;
|
|
369
|
+
st.deepEqual(qs.parse({ a: re }), { a: re });
|
|
370
|
+
st.end();
|
|
456
371
|
});
|
|
457
372
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
done();
|
|
373
|
+
t.test('can allow overwriting prototype properties', function (st) {
|
|
374
|
+
st.deepEqual(qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true }), { a: { hasOwnProperty: 'b' } }, { prototype: false });
|
|
375
|
+
st.deepEqual(qs.parse('hasOwnProperty=b', { allowPrototypes: true }), { hasOwnProperty: 'b' }, { prototype: false });
|
|
376
|
+
st.end();
|
|
463
377
|
});
|
|
464
378
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
const expected = Object.create(null);
|
|
379
|
+
t.test('can return plain objects', function (st) {
|
|
380
|
+
var expected = Object.create(null);
|
|
468
381
|
expected.a = Object.create(null);
|
|
469
382
|
expected.a.b = 'c';
|
|
470
383
|
expected.a.hasOwnProperty = 'd';
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
384
|
+
st.deepEqual(qs.parse('a[b]=c&a[hasOwnProperty]=d', { plainObjects: true }), expected);
|
|
385
|
+
st.deepEqual(qs.parse(null, { plainObjects: true }), Object.create(null));
|
|
386
|
+
var expectedArray = Object.create(null);
|
|
474
387
|
expectedArray.a = Object.create(null);
|
|
475
388
|
expectedArray.a['0'] = 'b';
|
|
476
389
|
expectedArray.a.c = 'd';
|
|
477
|
-
|
|
478
|
-
|
|
390
|
+
st.deepEqual(qs.parse('a[]=b&a[c]=d', { plainObjects: true }), expectedArray);
|
|
391
|
+
st.end();
|
|
479
392
|
});
|
|
480
393
|
});
|