qs 6.3.3 → 6.5.1
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/.editorconfig +1 -15
- package/.eslintignore +1 -0
- package/.eslintrc +4 -22
- package/CHANGELOG.md +57 -19
- package/LICENSE +28 -0
- package/README.md +82 -62
- package/dist/qs.js +129 -104
- package/lib/formats.js +1 -1
- package/lib/parse.js +40 -34
- package/lib/stringify.js +34 -31
- package/lib/utils.js +55 -39
- package/package.json +16 -19
- package/test/.eslintrc +15 -0
- package/test/parse.js +58 -72
- package/test/stringify.js +62 -34
- package/test/utils.js +11 -6
- package/.github/FUNDING.yml +0 -12
- package/.nycrc +0 -13
- package/LICENSE.md +0 -29
- package/bower.json +0 -21
- package/component.json +0 -15
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
|
-
|
|
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, defaults.encoder) : 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
|
-
|
|
61
|
+
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder);
|
|
62
|
+
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder))];
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -126,9 +123,9 @@ var stringify = function stringify(
|
|
|
126
123
|
|
|
127
124
|
module.exports = function (object, opts) {
|
|
128
125
|
var obj = object;
|
|
129
|
-
var options = opts
|
|
126
|
+
var options = opts ? utils.assign({}, opts) : {};
|
|
130
127
|
|
|
131
|
-
if (options.encoder !== null &&
|
|
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,10 +133,11 @@ 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 =
|
|
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
142
|
options.format = formats['default'];
|
|
145
143
|
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
|
|
@@ -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,20 +186,25 @@ module.exports = function (object, opts) {
|
|
|
188
186
|
if (skipNulls && obj[key] === null) {
|
|
189
187
|
continue;
|
|
190
188
|
}
|
|
191
|
-
|
|
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
|
|
|
206
|
-
|
|
206
|
+
var joined = keys.join(delimiter);
|
|
207
|
+
var prefix = options.addQueryPrefix === true ? '?' : '';
|
|
208
|
+
|
|
209
|
+
return joined.length > 0 ? prefix + joined : '';
|
|
207
210
|
};
|
package/lib/utils.js
CHANGED
|
@@ -11,7 +11,30 @@ var hexTable = (function () {
|
|
|
11
11
|
return array;
|
|
12
12
|
}());
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
var compactQueue = function compactQueue(queue) {
|
|
15
|
+
var obj;
|
|
16
|
+
|
|
17
|
+
while (queue.length) {
|
|
18
|
+
var item = queue.pop();
|
|
19
|
+
obj = item.obj[item.prop];
|
|
20
|
+
|
|
21
|
+
if (Array.isArray(obj)) {
|
|
22
|
+
var compacted = [];
|
|
23
|
+
|
|
24
|
+
for (var j = 0; j < obj.length; ++j) {
|
|
25
|
+
if (typeof obj[j] !== 'undefined') {
|
|
26
|
+
compacted.push(obj[j]);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
item.obj[item.prop] = compacted;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return obj;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
exports.arrayToObject = function arrayToObject(source, options) {
|
|
15
38
|
var obj = options && options.plainObjects ? Object.create(null) : {};
|
|
16
39
|
for (var i = 0; i < source.length; ++i) {
|
|
17
40
|
if (typeof source[i] !== 'undefined') {
|
|
@@ -22,7 +45,7 @@ exports.arrayToObject = function (source, options) {
|
|
|
22
45
|
return obj;
|
|
23
46
|
};
|
|
24
47
|
|
|
25
|
-
exports.merge = function (target, source, options) {
|
|
48
|
+
exports.merge = function merge(target, source, options) {
|
|
26
49
|
if (!source) {
|
|
27
50
|
return target;
|
|
28
51
|
}
|
|
@@ -30,8 +53,8 @@ exports.merge = function (target, source, options) {
|
|
|
30
53
|
if (typeof source !== 'object') {
|
|
31
54
|
if (Array.isArray(target)) {
|
|
32
55
|
target.push(source);
|
|
33
|
-
} else if (
|
|
34
|
-
if (
|
|
56
|
+
} else if (typeof target === 'object') {
|
|
57
|
+
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
|
|
35
58
|
target[source] = true;
|
|
36
59
|
}
|
|
37
60
|
} else {
|
|
@@ -41,7 +64,7 @@ exports.merge = function (target, source, options) {
|
|
|
41
64
|
return target;
|
|
42
65
|
}
|
|
43
66
|
|
|
44
|
-
if (
|
|
67
|
+
if (typeof target !== 'object') {
|
|
45
68
|
return [target].concat(source);
|
|
46
69
|
}
|
|
47
70
|
|
|
@@ -68,7 +91,7 @@ exports.merge = function (target, source, options) {
|
|
|
68
91
|
return Object.keys(source).reduce(function (acc, key) {
|
|
69
92
|
var value = source[key];
|
|
70
93
|
|
|
71
|
-
if (
|
|
94
|
+
if (has.call(acc, key)) {
|
|
72
95
|
acc[key] = exports.merge(acc[key], value, options);
|
|
73
96
|
} else {
|
|
74
97
|
acc[key] = value;
|
|
@@ -77,6 +100,13 @@ exports.merge = function (target, source, options) {
|
|
|
77
100
|
}, mergeTarget);
|
|
78
101
|
};
|
|
79
102
|
|
|
103
|
+
exports.assign = function assignSingleSource(target, source) {
|
|
104
|
+
return Object.keys(source).reduce(function (acc, key) {
|
|
105
|
+
acc[key] = source[key];
|
|
106
|
+
return acc;
|
|
107
|
+
}, target);
|
|
108
|
+
};
|
|
109
|
+
|
|
80
110
|
exports.decode = function (str) {
|
|
81
111
|
try {
|
|
82
112
|
return decodeURIComponent(str.replace(/\+/g, ' '));
|
|
@@ -85,7 +115,7 @@ exports.decode = function (str) {
|
|
|
85
115
|
}
|
|
86
116
|
};
|
|
87
117
|
|
|
88
|
-
exports.encode = function (str) {
|
|
118
|
+
exports.encode = function encode(str) {
|
|
89
119
|
// This code was originally written by Brian White (mscdex) for the io.js core querystring library.
|
|
90
120
|
// It has been adapted here for stricter adherence to RFC 3986
|
|
91
121
|
if (str.length === 0) {
|
|
@@ -128,7 +158,6 @@ exports.encode = function (str) {
|
|
|
128
158
|
|
|
129
159
|
i += 1;
|
|
130
160
|
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
|
|
131
|
-
/* eslint operator-linebreak: [2, "before"] */
|
|
132
161
|
out += hexTable[0xF0 | (c >> 18)]
|
|
133
162
|
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
|
|
134
163
|
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
|
|
@@ -138,46 +167,33 @@ exports.encode = function (str) {
|
|
|
138
167
|
return out;
|
|
139
168
|
};
|
|
140
169
|
|
|
141
|
-
exports.compact = function (
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
for (var i = 0; i < obj.length; ++i) {
|
|
158
|
-
if (obj[i] && typeof obj[i] === 'object') {
|
|
159
|
-
compacted.push(exports.compact(obj[i], refs));
|
|
160
|
-
} else if (typeof obj[i] !== 'undefined') {
|
|
161
|
-
compacted.push(obj[i]);
|
|
170
|
+
exports.compact = function compact(value) {
|
|
171
|
+
var queue = [{ obj: { o: value }, prop: 'o' }];
|
|
172
|
+
var refs = [];
|
|
173
|
+
|
|
174
|
+
for (var i = 0; i < queue.length; ++i) {
|
|
175
|
+
var item = queue[i];
|
|
176
|
+
var obj = item.obj[item.prop];
|
|
177
|
+
|
|
178
|
+
var keys = Object.keys(obj);
|
|
179
|
+
for (var j = 0; j < keys.length; ++j) {
|
|
180
|
+
var key = keys[j];
|
|
181
|
+
var val = obj[key];
|
|
182
|
+
if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
|
|
183
|
+
queue.push({ obj: obj, prop: key });
|
|
184
|
+
refs.push(val);
|
|
162
185
|
}
|
|
163
186
|
}
|
|
164
|
-
|
|
165
|
-
return compacted;
|
|
166
187
|
}
|
|
167
188
|
|
|
168
|
-
|
|
169
|
-
keys.forEach(function (key) {
|
|
170
|
-
obj[key] = exports.compact(obj[key], refs);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
return obj;
|
|
189
|
+
return compactQueue(queue);
|
|
174
190
|
};
|
|
175
191
|
|
|
176
|
-
exports.isRegExp = function (obj) {
|
|
192
|
+
exports.isRegExp = function isRegExp(obj) {
|
|
177
193
|
return Object.prototype.toString.call(obj) === '[object RegExp]';
|
|
178
194
|
};
|
|
179
195
|
|
|
180
|
-
exports.isBuffer = function (obj) {
|
|
196
|
+
exports.isBuffer = function isBuffer(obj) {
|
|
181
197
|
if (obj === null || typeof obj === 'undefined') {
|
|
182
198
|
return false;
|
|
183
199
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "qs",
|
|
3
3
|
"description": "A querystring parser that supports nesting and arrays, with a depth limit",
|
|
4
4
|
"homepage": "https://github.com/ljharb/qs",
|
|
5
|
-
"version": "6.
|
|
5
|
+
"version": "6.5.1",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/ljharb/qs.git"
|
|
@@ -22,32 +22,29 @@
|
|
|
22
22
|
"engines": {
|
|
23
23
|
"node": ">=0.6"
|
|
24
24
|
},
|
|
25
|
+
"dependencies": {},
|
|
25
26
|
"devDependencies": {
|
|
26
|
-
"@ljharb/eslint-config": "^
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"eslint": "^
|
|
27
|
+
"@ljharb/eslint-config": "^12.2.1",
|
|
28
|
+
"browserify": "^14.4.0",
|
|
29
|
+
"covert": "^1.1.0",
|
|
30
|
+
"editorconfig-tools": "^0.1.1",
|
|
31
|
+
"eslint": "^4.6.1",
|
|
31
32
|
"evalmd": "^0.0.17",
|
|
32
|
-
"iconv-lite": "^0.4.
|
|
33
|
-
"in-publish": "^2.0.1",
|
|
33
|
+
"iconv-lite": "^0.4.18",
|
|
34
34
|
"mkdirp": "^0.5.1",
|
|
35
|
-
"nyc": "^10.3.2",
|
|
36
35
|
"qs-iconv": "^1.0.4",
|
|
37
|
-
"safe-publish-latest": "^
|
|
38
|
-
"
|
|
39
|
-
"tape": "^5.4.0"
|
|
36
|
+
"safe-publish-latest": "^1.1.1",
|
|
37
|
+
"tape": "^4.8.0"
|
|
40
38
|
},
|
|
41
39
|
"scripts": {
|
|
42
|
-
"
|
|
43
|
-
"prepublish": "not-in-publish || npm run prepublishOnly",
|
|
40
|
+
"prepublish": "safe-publish-latest && npm run dist",
|
|
44
41
|
"pretest": "npm run --silent readme && npm run --silent lint",
|
|
45
|
-
"test": "npm run --silent
|
|
46
|
-
"tests-only": "
|
|
47
|
-
"posttest": "aud --production",
|
|
42
|
+
"test": "npm run --silent coverage",
|
|
43
|
+
"tests-only": "node test",
|
|
48
44
|
"readme": "evalmd README.md",
|
|
49
|
-
"
|
|
50
|
-
"lint": "eslint
|
|
45
|
+
"prelint": "editorconfig-tools check * lib/* test/*",
|
|
46
|
+
"lint": "eslint lib/*.js test/*.js",
|
|
47
|
+
"coverage": "covert test",
|
|
51
48
|
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js"
|
|
52
49
|
},
|
|
53
50
|
"license": "BSD-3-Clause"
|
package/test/.eslintrc
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"rules": {
|
|
3
|
+
"array-bracket-newline": 0,
|
|
4
|
+
"array-element-newline": 0,
|
|
5
|
+
"consistent-return": 2,
|
|
6
|
+
"max-lines": 0,
|
|
7
|
+
"max-nested-callbacks": [2, 3],
|
|
8
|
+
"max-statements": 0,
|
|
9
|
+
"no-buffer-constructor": 0,
|
|
10
|
+
"no-extend-native": 0,
|
|
11
|
+
"no-magic-numbers": 0,
|
|
12
|
+
"object-curly-newline": 0,
|
|
13
|
+
"sort-keys": 0
|
|
14
|
+
}
|
|
15
|
+
}
|
package/test/parse.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
var test = require('tape');
|
|
4
4
|
var qs = require('../');
|
|
5
|
+
var utils = require('../lib/utils');
|
|
5
6
|
var iconv = require('iconv-lite');
|
|
6
|
-
var SaferBuffer = require('safer-buffer').Buffer;
|
|
7
7
|
|
|
8
8
|
test('parse()', function (t) {
|
|
9
9
|
t.test('parses a simple string', function (st) {
|
|
@@ -231,7 +231,7 @@ test('parse()', function (t) {
|
|
|
231
231
|
});
|
|
232
232
|
|
|
233
233
|
t.test('parses buffers correctly', function (st) {
|
|
234
|
-
var b =
|
|
234
|
+
var b = new Buffer('test');
|
|
235
235
|
st.deepEqual(qs.parse({ a: b }), { a: b });
|
|
236
236
|
st.end();
|
|
237
237
|
});
|
|
@@ -256,7 +256,7 @@ test('parse()', function (t) {
|
|
|
256
256
|
st.end();
|
|
257
257
|
});
|
|
258
258
|
|
|
259
|
-
t.test('should not throw when a native prototype has an enumerable property', function (st) {
|
|
259
|
+
t.test('should not throw when a native prototype has an enumerable property', { parallel: false }, function (st) {
|
|
260
260
|
Object.prototype.crash = '';
|
|
261
261
|
Array.prototype.crash = '';
|
|
262
262
|
st.doesNotThrow(qs.parse.bind(null, 'a=b'));
|
|
@@ -301,14 +301,14 @@ test('parse()', function (t) {
|
|
|
301
301
|
});
|
|
302
302
|
|
|
303
303
|
t.test('allows disabling array parsing', function (st) {
|
|
304
|
-
|
|
305
|
-
st.
|
|
306
|
-
|
|
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');
|
|
304
|
+
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { parseArrays: false }), { a: { 0: 'b', 1: 'c' } });
|
|
305
|
+
st.end();
|
|
306
|
+
});
|
|
311
307
|
|
|
308
|
+
t.test('allows for query string prefix', function (st) {
|
|
309
|
+
st.deepEqual(qs.parse('?foo=bar', { ignoreQueryPrefix: true }), { foo: 'bar' });
|
|
310
|
+
st.deepEqual(qs.parse('foo=bar', { ignoreQueryPrefix: true }), { foo: 'bar' });
|
|
311
|
+
st.deepEqual(qs.parse('?foo=bar', { ignoreQueryPrefix: false }), { '?foo': 'bar' });
|
|
312
312
|
st.end();
|
|
313
313
|
});
|
|
314
314
|
|
|
@@ -396,6 +396,33 @@ test('parse()', function (t) {
|
|
|
396
396
|
st.end();
|
|
397
397
|
});
|
|
398
398
|
|
|
399
|
+
t.test('does not crash when parsing deep objects', function (st) {
|
|
400
|
+
var parsed;
|
|
401
|
+
var str = 'foo';
|
|
402
|
+
|
|
403
|
+
for (var i = 0; i < 5000; i++) {
|
|
404
|
+
str += '[p]';
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
str += '=bar';
|
|
408
|
+
|
|
409
|
+
st.doesNotThrow(function () {
|
|
410
|
+
parsed = qs.parse(str, { depth: 5000 });
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
st.equal('foo' in parsed, true, 'parsed has "foo" property');
|
|
414
|
+
|
|
415
|
+
var depth = 0;
|
|
416
|
+
var ref = parsed.foo;
|
|
417
|
+
while ((ref = ref.p)) {
|
|
418
|
+
depth += 1;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
st.equal(depth, 5000, 'parsed is 5000 properties deep');
|
|
422
|
+
|
|
423
|
+
st.end();
|
|
424
|
+
});
|
|
425
|
+
|
|
399
426
|
t.test('parses null objects correctly', { skip: !Object.create }, function (st) {
|
|
400
427
|
var a = Object.create(null);
|
|
401
428
|
a.b = 'c';
|
|
@@ -480,73 +507,13 @@ test('parse()', function (t) {
|
|
|
480
507
|
|
|
481
508
|
st.deepEqual(
|
|
482
509
|
qs.parse('a[b]=c&a=toString', { plainObjects: true }),
|
|
483
|
-
{
|
|
510
|
+
{ a: { b: 'c', toString: true } },
|
|
484
511
|
'can overwrite prototype with plainObjects true'
|
|
485
512
|
);
|
|
486
513
|
|
|
487
514
|
st.end();
|
|
488
515
|
});
|
|
489
516
|
|
|
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
517
|
t.test('can return null objects', { skip: !Object.create }, function (st) {
|
|
551
518
|
var expected = Object.create(null);
|
|
552
519
|
expected.a = Object.create(null);
|
|
@@ -572,16 +539,35 @@ test('parse()', function (t) {
|
|
|
572
539
|
result.push(parseInt(parts[1], 16));
|
|
573
540
|
parts = reg.exec(str);
|
|
574
541
|
}
|
|
575
|
-
return iconv.decode(
|
|
542
|
+
return iconv.decode(new Buffer(result), 'shift_jis').toString();
|
|
576
543
|
}
|
|
577
544
|
}), { 県: '大阪府' });
|
|
578
545
|
st.end();
|
|
579
546
|
});
|
|
580
547
|
|
|
548
|
+
t.test('receives the default decoder as a second argument', function (st) {
|
|
549
|
+
st.plan(1);
|
|
550
|
+
qs.parse('a', {
|
|
551
|
+
decoder: function (str, defaultDecoder) {
|
|
552
|
+
st.equal(defaultDecoder, utils.decode);
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
st.end();
|
|
556
|
+
});
|
|
557
|
+
|
|
581
558
|
t.test('throws error with wrong decoder', function (st) {
|
|
582
559
|
st['throws'](function () {
|
|
583
560
|
qs.parse({}, { decoder: 'string' });
|
|
584
561
|
}, new TypeError('Decoder has to be a function.'));
|
|
585
562
|
st.end();
|
|
586
563
|
});
|
|
564
|
+
|
|
565
|
+
t.test('does not mutate the options argument', function (st) {
|
|
566
|
+
var options = {};
|
|
567
|
+
qs.parse('a[b]=true', options);
|
|
568
|
+
st.deepEqual(options, {});
|
|
569
|
+
st.end();
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
t.end();
|
|
587
573
|
});
|