qs 6.5.3 → 6.6.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/.editorconfig +1 -14
- package/.eslintignore +1 -0
- package/.eslintrc +6 -22
- package/CHANGELOG.md +12 -20
- package/LICENSE +28 -0
- package/README.md +107 -56
- package/dist/qs.js +133 -44
- package/lib/formats.js +1 -1
- package/lib/parse.js +60 -9
- package/lib/stringify.js +42 -17
- package/lib/utils.js +30 -17
- package/package.json +15 -17
- package/test/.eslintrc +17 -0
- package/test/parse.js +80 -70
- package/test/stringify.js +32 -25
- package/test/utils.js +52 -28
- 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,13 +4,13 @@ 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
|
};
|
|
@@ -24,18 +24,24 @@ var pushToArray = function (arr, valueOrArray) {
|
|
|
24
24
|
var toISO = Date.prototype.toISOString;
|
|
25
25
|
|
|
26
26
|
var defaults = {
|
|
27
|
+
addQueryPrefix: false,
|
|
28
|
+
allowDots: false,
|
|
29
|
+
charset: 'utf-8',
|
|
30
|
+
charsetSentinel: false,
|
|
27
31
|
delimiter: '&',
|
|
28
32
|
encode: true,
|
|
29
33
|
encoder: utils.encode,
|
|
30
34
|
encodeValuesOnly: false,
|
|
31
|
-
|
|
35
|
+
// deprecated
|
|
36
|
+
indices: false,
|
|
37
|
+
serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching
|
|
32
38
|
return toISO.call(date);
|
|
33
39
|
},
|
|
34
40
|
skipNulls: false,
|
|
35
41
|
strictNullHandling: false
|
|
36
42
|
};
|
|
37
43
|
|
|
38
|
-
var stringify = function stringify(
|
|
44
|
+
var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
39
45
|
object,
|
|
40
46
|
prefix,
|
|
41
47
|
generateArrayPrefix,
|
|
@@ -47,7 +53,8 @@ var stringify = function stringify(
|
|
|
47
53
|
allowDots,
|
|
48
54
|
serializeDate,
|
|
49
55
|
formatter,
|
|
50
|
-
encodeValuesOnly
|
|
56
|
+
encodeValuesOnly,
|
|
57
|
+
charset
|
|
51
58
|
) {
|
|
52
59
|
var obj = object;
|
|
53
60
|
if (typeof filter === 'function') {
|
|
@@ -58,7 +65,7 @@ var stringify = function stringify(
|
|
|
58
65
|
|
|
59
66
|
if (obj === null) {
|
|
60
67
|
if (strictNullHandling) {
|
|
61
|
-
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder) : prefix;
|
|
68
|
+
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset) : prefix;
|
|
62
69
|
}
|
|
63
70
|
|
|
64
71
|
obj = '';
|
|
@@ -66,8 +73,8 @@ var stringify = function stringify(
|
|
|
66
73
|
|
|
67
74
|
if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
|
|
68
75
|
if (encoder) {
|
|
69
|
-
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder);
|
|
70
|
-
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder))];
|
|
76
|
+
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset);
|
|
77
|
+
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset))];
|
|
71
78
|
}
|
|
72
79
|
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
73
80
|
}
|
|
@@ -79,7 +86,7 @@ var stringify = function stringify(
|
|
|
79
86
|
}
|
|
80
87
|
|
|
81
88
|
var objKeys;
|
|
82
|
-
if (isArray(filter)) {
|
|
89
|
+
if (Array.isArray(filter)) {
|
|
83
90
|
objKeys = filter;
|
|
84
91
|
} else {
|
|
85
92
|
var keys = Object.keys(obj);
|
|
@@ -93,7 +100,7 @@ var stringify = function stringify(
|
|
|
93
100
|
continue;
|
|
94
101
|
}
|
|
95
102
|
|
|
96
|
-
if (isArray(obj)) {
|
|
103
|
+
if (Array.isArray(obj)) {
|
|
97
104
|
pushToArray(values, stringify(
|
|
98
105
|
obj[key],
|
|
99
106
|
generateArrayPrefix(prefix, key),
|
|
@@ -106,7 +113,8 @@ var stringify = function stringify(
|
|
|
106
113
|
allowDots,
|
|
107
114
|
serializeDate,
|
|
108
115
|
formatter,
|
|
109
|
-
encodeValuesOnly
|
|
116
|
+
encodeValuesOnly,
|
|
117
|
+
charset
|
|
110
118
|
));
|
|
111
119
|
} else {
|
|
112
120
|
pushToArray(values, stringify(
|
|
@@ -121,7 +129,8 @@ var stringify = function stringify(
|
|
|
121
129
|
allowDots,
|
|
122
130
|
serializeDate,
|
|
123
131
|
formatter,
|
|
124
|
-
encodeValuesOnly
|
|
132
|
+
encodeValuesOnly,
|
|
133
|
+
charset
|
|
125
134
|
));
|
|
126
135
|
}
|
|
127
136
|
}
|
|
@@ -133,7 +142,7 @@ module.exports = function (object, opts) {
|
|
|
133
142
|
var obj = object;
|
|
134
143
|
var options = opts ? utils.assign({}, opts) : {};
|
|
135
144
|
|
|
136
|
-
if (options.encoder !== null &&
|
|
145
|
+
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
|
|
137
146
|
throw new TypeError('Encoder has to be a function.');
|
|
138
147
|
}
|
|
139
148
|
|
|
@@ -143,9 +152,14 @@ module.exports = function (object, opts) {
|
|
|
143
152
|
var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode;
|
|
144
153
|
var encoder = typeof options.encoder === 'function' ? options.encoder : defaults.encoder;
|
|
145
154
|
var sort = typeof options.sort === 'function' ? options.sort : null;
|
|
146
|
-
var allowDots = typeof options.allowDots === 'undefined' ?
|
|
155
|
+
var allowDots = typeof options.allowDots === 'undefined' ? defaults.allowDots : !!options.allowDots;
|
|
147
156
|
var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
|
|
148
157
|
var encodeValuesOnly = typeof options.encodeValuesOnly === 'boolean' ? options.encodeValuesOnly : defaults.encodeValuesOnly;
|
|
158
|
+
var charset = options.charset || defaults.charset;
|
|
159
|
+
if (typeof options.charset !== 'undefined' && options.charset !== 'utf-8' && options.charset !== 'iso-8859-1') {
|
|
160
|
+
throw new Error('The charset option must be either utf-8, iso-8859-1, or undefined');
|
|
161
|
+
}
|
|
162
|
+
|
|
149
163
|
if (typeof options.format === 'undefined') {
|
|
150
164
|
options.format = formats['default'];
|
|
151
165
|
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
|
|
@@ -158,7 +172,7 @@ module.exports = function (object, opts) {
|
|
|
158
172
|
if (typeof options.filter === 'function') {
|
|
159
173
|
filter = options.filter;
|
|
160
174
|
obj = filter('', obj);
|
|
161
|
-
} else if (isArray(options.filter)) {
|
|
175
|
+
} else if (Array.isArray(options.filter)) {
|
|
162
176
|
filter = options.filter;
|
|
163
177
|
objKeys = filter;
|
|
164
178
|
}
|
|
@@ -206,12 +220,23 @@ module.exports = function (object, opts) {
|
|
|
206
220
|
allowDots,
|
|
207
221
|
serializeDate,
|
|
208
222
|
formatter,
|
|
209
|
-
encodeValuesOnly
|
|
223
|
+
encodeValuesOnly,
|
|
224
|
+
charset
|
|
210
225
|
));
|
|
211
226
|
}
|
|
212
227
|
|
|
213
228
|
var joined = keys.join(delimiter);
|
|
214
229
|
var prefix = options.addQueryPrefix === true ? '?' : '';
|
|
215
230
|
|
|
231
|
+
if (options.charsetSentinel) {
|
|
232
|
+
if (charset === 'iso-8859-1') {
|
|
233
|
+
// encodeURIComponent('✓'), the "numeric entity" representation of a checkmark
|
|
234
|
+
prefix += 'utf8=%26%2310003%3B&';
|
|
235
|
+
} else {
|
|
236
|
+
// encodeURIComponent('✓')
|
|
237
|
+
prefix += 'utf8=%E2%9C%93&';
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
216
241
|
return joined.length > 0 ? prefix + joined : '';
|
|
217
242
|
};
|
package/lib/utils.js
CHANGED
|
@@ -12,11 +12,9 @@ var hexTable = (function () {
|
|
|
12
12
|
}());
|
|
13
13
|
|
|
14
14
|
var compactQueue = function compactQueue(queue) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
while (queue.length) {
|
|
15
|
+
while (queue.length > 1) {
|
|
18
16
|
var item = queue.pop();
|
|
19
|
-
obj = item.obj[item.prop];
|
|
17
|
+
var obj = item.obj[item.prop];
|
|
20
18
|
|
|
21
19
|
if (Array.isArray(obj)) {
|
|
22
20
|
var compacted = [];
|
|
@@ -30,8 +28,6 @@ var compactQueue = function compactQueue(queue) {
|
|
|
30
28
|
item.obj[item.prop] = compacted;
|
|
31
29
|
}
|
|
32
30
|
}
|
|
33
|
-
|
|
34
|
-
return obj;
|
|
35
31
|
};
|
|
36
32
|
|
|
37
33
|
var arrayToObject = function arrayToObject(source, options) {
|
|
@@ -53,7 +49,7 @@ var merge = function merge(target, source, options) {
|
|
|
53
49
|
if (typeof source !== 'object') {
|
|
54
50
|
if (Array.isArray(target)) {
|
|
55
51
|
target.push(source);
|
|
56
|
-
} else if (
|
|
52
|
+
} else if (typeof target === 'object') {
|
|
57
53
|
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
|
|
58
54
|
target[source] = true;
|
|
59
55
|
}
|
|
@@ -64,7 +60,7 @@ var merge = function merge(target, source, options) {
|
|
|
64
60
|
return target;
|
|
65
61
|
}
|
|
66
62
|
|
|
67
|
-
if (
|
|
63
|
+
if (typeof target !== 'object') {
|
|
68
64
|
return [target].concat(source);
|
|
69
65
|
}
|
|
70
66
|
|
|
@@ -76,9 +72,8 @@ var merge = function merge(target, source, options) {
|
|
|
76
72
|
if (Array.isArray(target) && Array.isArray(source)) {
|
|
77
73
|
source.forEach(function (item, i) {
|
|
78
74
|
if (has.call(target, i)) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
target[i] = merge(targetItem, item, options);
|
|
75
|
+
if (target[i] && typeof target[i] === 'object') {
|
|
76
|
+
target[i] = merge(target[i], item, options);
|
|
82
77
|
} else {
|
|
83
78
|
target.push(item);
|
|
84
79
|
}
|
|
@@ -108,15 +103,21 @@ var assign = function assignSingleSource(target, source) {
|
|
|
108
103
|
}, target);
|
|
109
104
|
};
|
|
110
105
|
|
|
111
|
-
var decode = function (str) {
|
|
106
|
+
var decode = function (str, decoder, charset) {
|
|
107
|
+
var strWithoutPlus = str.replace(/\+/g, ' ');
|
|
108
|
+
if (charset === 'iso-8859-1') {
|
|
109
|
+
// unescape never throws, no try...catch needed:
|
|
110
|
+
return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape);
|
|
111
|
+
}
|
|
112
|
+
// utf-8
|
|
112
113
|
try {
|
|
113
|
-
return decodeURIComponent(
|
|
114
|
+
return decodeURIComponent(strWithoutPlus);
|
|
114
115
|
} catch (e) {
|
|
115
|
-
return
|
|
116
|
+
return strWithoutPlus;
|
|
116
117
|
}
|
|
117
118
|
};
|
|
118
119
|
|
|
119
|
-
var encode = function encode(str) {
|
|
120
|
+
var encode = function encode(str, defaultEncoder, charset) {
|
|
120
121
|
// This code was originally written by Brian White (mscdex) for the io.js core querystring library.
|
|
121
122
|
// It has been adapted here for stricter adherence to RFC 3986
|
|
122
123
|
if (str.length === 0) {
|
|
@@ -125,6 +126,12 @@ var encode = function encode(str) {
|
|
|
125
126
|
|
|
126
127
|
var string = typeof str === 'string' ? str : String(str);
|
|
127
128
|
|
|
129
|
+
if (charset === 'iso-8859-1') {
|
|
130
|
+
return escape(string).replace(/%u[0-9a-f]{4}/gi, function ($0) {
|
|
131
|
+
return '%26%23' + parseInt($0.slice(2), 16) + '%3B';
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
128
135
|
var out = '';
|
|
129
136
|
for (var i = 0; i < string.length; ++i) {
|
|
130
137
|
var c = string.charCodeAt(i);
|
|
@@ -159,7 +166,6 @@ var encode = function encode(str) {
|
|
|
159
166
|
|
|
160
167
|
i += 1;
|
|
161
168
|
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
|
|
162
|
-
/* eslint operator-linebreak: [2, "before"] */
|
|
163
169
|
out += hexTable[0xF0 | (c >> 18)]
|
|
164
170
|
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
|
|
165
171
|
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
|
|
@@ -188,7 +194,9 @@ var compact = function compact(value) {
|
|
|
188
194
|
}
|
|
189
195
|
}
|
|
190
196
|
|
|
191
|
-
|
|
197
|
+
compactQueue(queue);
|
|
198
|
+
|
|
199
|
+
return value;
|
|
192
200
|
};
|
|
193
201
|
|
|
194
202
|
var isRegExp = function isRegExp(obj) {
|
|
@@ -203,9 +211,14 @@ var isBuffer = function isBuffer(obj) {
|
|
|
203
211
|
return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
|
|
204
212
|
};
|
|
205
213
|
|
|
214
|
+
var combine = function combine(a, b) {
|
|
215
|
+
return [].concat(a, b);
|
|
216
|
+
};
|
|
217
|
+
|
|
206
218
|
module.exports = {
|
|
207
219
|
arrayToObject: arrayToObject,
|
|
208
220
|
assign: assign,
|
|
221
|
+
combine: combine,
|
|
209
222
|
compact: compact,
|
|
210
223
|
decode: decode,
|
|
211
224
|
encode: encode,
|
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.6.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/ljharb/qs.git"
|
|
@@ -22,32 +22,30 @@
|
|
|
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": "^13.0.0",
|
|
28
|
+
"browserify": "^16.2.3",
|
|
29
|
+
"covert": "^1.1.0",
|
|
30
|
+
"editorconfig-tools": "^0.1.1",
|
|
31
|
+
"eslint": "^5.9.0",
|
|
31
32
|
"evalmd": "^0.0.17",
|
|
32
33
|
"iconv-lite": "^0.4.24",
|
|
33
|
-
"in-publish": "^2.0.1",
|
|
34
34
|
"mkdirp": "^0.5.1",
|
|
35
|
-
"nyc": "^10.3.2",
|
|
36
35
|
"qs-iconv": "^1.0.4",
|
|
37
|
-
"safe-publish-latest": "^
|
|
36
|
+
"safe-publish-latest": "^1.1.2",
|
|
38
37
|
"safer-buffer": "^2.1.2",
|
|
39
|
-
"tape": "^
|
|
38
|
+
"tape": "^4.9.1"
|
|
40
39
|
},
|
|
41
40
|
"scripts": {
|
|
42
|
-
"
|
|
43
|
-
"prepublish": "not-in-publish || npm run prepublishOnly",
|
|
41
|
+
"prepublish": "safe-publish-latest && npm run dist",
|
|
44
42
|
"pretest": "npm run --silent readme && npm run --silent lint",
|
|
45
|
-
"test": "npm run --silent
|
|
46
|
-
"tests-only": "
|
|
47
|
-
"posttest": "aud --production",
|
|
43
|
+
"test": "npm run --silent coverage",
|
|
44
|
+
"tests-only": "node test",
|
|
48
45
|
"readme": "evalmd README.md",
|
|
49
|
-
"postlint": "
|
|
50
|
-
"lint": "eslint
|
|
46
|
+
"postlint": "editorconfig-tools check * lib/* test/*",
|
|
47
|
+
"lint": "eslint lib/*.js test/*.js",
|
|
48
|
+
"coverage": "covert test",
|
|
51
49
|
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js"
|
|
52
50
|
},
|
|
53
51
|
"license": "BSD-3-Clause"
|
package/test/.eslintrc
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"rules": {
|
|
3
|
+
"array-bracket-newline": 0,
|
|
4
|
+
"array-element-newline": 0,
|
|
5
|
+
"consistent-return": 2,
|
|
6
|
+
"function-paren-newline": 0,
|
|
7
|
+
"max-lines": 0,
|
|
8
|
+
"max-lines-per-function": 0,
|
|
9
|
+
"max-nested-callbacks": [2, 3],
|
|
10
|
+
"max-statements": 0,
|
|
11
|
+
"no-buffer-constructor": 0,
|
|
12
|
+
"no-extend-native": 0,
|
|
13
|
+
"no-magic-numbers": 0,
|
|
14
|
+
"object-curly-newline": 0,
|
|
15
|
+
"sort-keys": 0
|
|
16
|
+
}
|
|
17
|
+
}
|
package/test/parse.js
CHANGED
|
@@ -237,14 +237,6 @@ test('parse()', function (t) {
|
|
|
237
237
|
st.end();
|
|
238
238
|
});
|
|
239
239
|
|
|
240
|
-
t.test('parses jquery-param strings', function (st) {
|
|
241
|
-
// readable = 'filter[0][]=int1&filter[0][]==&filter[0][]=77&filter[]=and&filter[2][]=int2&filter[2][]==&filter[2][]=8'
|
|
242
|
-
var encoded = 'filter%5B0%5D%5B%5D=int1&filter%5B0%5D%5B%5D=%3D&filter%5B0%5D%5B%5D=77&filter%5B%5D=and&filter%5B2%5D%5B%5D=int2&filter%5B2%5D%5B%5D=%3D&filter%5B2%5D%5B%5D=8';
|
|
243
|
-
var expected = { filter: [['int1', '=', '77'], 'and', ['int2', '=', '8']] };
|
|
244
|
-
st.deepEqual(qs.parse(encoded), expected);
|
|
245
|
-
st.end();
|
|
246
|
-
});
|
|
247
|
-
|
|
248
240
|
t.test('continues parsing when no parent is found', function (st) {
|
|
249
241
|
st.deepEqual(qs.parse('[]=&a=b'), { 0: '', a: 'b' });
|
|
250
242
|
st.deepEqual(qs.parse('[]&a=b', { strictNullHandling: true }), { 0: null, a: 'b' });
|
|
@@ -523,73 +515,13 @@ test('parse()', function (t) {
|
|
|
523
515
|
|
|
524
516
|
st.deepEqual(
|
|
525
517
|
qs.parse('a[b]=c&a=toString', { plainObjects: true }),
|
|
526
|
-
{
|
|
518
|
+
{ a: { b: 'c', toString: true } },
|
|
527
519
|
'can overwrite prototype with plainObjects true'
|
|
528
520
|
);
|
|
529
521
|
|
|
530
522
|
st.end();
|
|
531
523
|
});
|
|
532
524
|
|
|
533
|
-
t.test('dunder proto is ignored', function (st) {
|
|
534
|
-
var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
|
|
535
|
-
var result = qs.parse(payload, { allowPrototypes: true });
|
|
536
|
-
|
|
537
|
-
st.deepEqual(
|
|
538
|
-
result,
|
|
539
|
-
{
|
|
540
|
-
categories: {
|
|
541
|
-
length: '42'
|
|
542
|
-
}
|
|
543
|
-
},
|
|
544
|
-
'silent [[Prototype]] payload'
|
|
545
|
-
);
|
|
546
|
-
|
|
547
|
-
var plainResult = qs.parse(payload, { allowPrototypes: true, plainObjects: true });
|
|
548
|
-
|
|
549
|
-
st.deepEqual(
|
|
550
|
-
plainResult,
|
|
551
|
-
{
|
|
552
|
-
__proto__: null,
|
|
553
|
-
categories: {
|
|
554
|
-
__proto__: null,
|
|
555
|
-
length: '42'
|
|
556
|
-
}
|
|
557
|
-
},
|
|
558
|
-
'silent [[Prototype]] payload: plain objects'
|
|
559
|
-
);
|
|
560
|
-
|
|
561
|
-
var query = qs.parse('categories[__proto__]=cats&categories[__proto__]=dogs&categories[some][json]=toInject', { allowPrototypes: true });
|
|
562
|
-
|
|
563
|
-
st.notOk(Array.isArray(query.categories), 'is not an array');
|
|
564
|
-
st.notOk(query.categories instanceof Array, 'is not instanceof an array');
|
|
565
|
-
st.deepEqual(query.categories, { some: { json: 'toInject' } });
|
|
566
|
-
st.equal(JSON.stringify(query.categories), '{"some":{"json":"toInject"}}', 'stringifies as a non-array');
|
|
567
|
-
|
|
568
|
-
st.deepEqual(
|
|
569
|
-
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true }),
|
|
570
|
-
{
|
|
571
|
-
foo: {
|
|
572
|
-
bar: 'stuffs'
|
|
573
|
-
}
|
|
574
|
-
},
|
|
575
|
-
'hidden values'
|
|
576
|
-
);
|
|
577
|
-
|
|
578
|
-
st.deepEqual(
|
|
579
|
-
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true, plainObjects: true }),
|
|
580
|
-
{
|
|
581
|
-
__proto__: null,
|
|
582
|
-
foo: {
|
|
583
|
-
__proto__: null,
|
|
584
|
-
bar: 'stuffs'
|
|
585
|
-
}
|
|
586
|
-
},
|
|
587
|
-
'hidden values: plain objects'
|
|
588
|
-
);
|
|
589
|
-
|
|
590
|
-
st.end();
|
|
591
|
-
});
|
|
592
|
-
|
|
593
525
|
t.test('can return null objects', { skip: !Object.create }, function (st) {
|
|
594
526
|
var expected = Object.create(null);
|
|
595
527
|
expected.a = Object.create(null);
|
|
@@ -615,7 +547,7 @@ test('parse()', function (t) {
|
|
|
615
547
|
result.push(parseInt(parts[1], 16));
|
|
616
548
|
parts = reg.exec(str);
|
|
617
549
|
}
|
|
618
|
-
return
|
|
550
|
+
return iconv.decode(SaferBuffer.from(result), 'shift_jis').toString();
|
|
619
551
|
}
|
|
620
552
|
}), { 県: '大阪府' });
|
|
621
553
|
st.end();
|
|
@@ -645,5 +577,83 @@ test('parse()', function (t) {
|
|
|
645
577
|
st.end();
|
|
646
578
|
});
|
|
647
579
|
|
|
580
|
+
t.test('throws if an invalid charset is specified', function (st) {
|
|
581
|
+
st['throws'](function () {
|
|
582
|
+
qs.parse('a=b', { charset: 'foobar' });
|
|
583
|
+
}, new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'));
|
|
584
|
+
st.end();
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
t.test('parses an iso-8859-1 string if asked to', function (st) {
|
|
588
|
+
st.deepEqual(qs.parse('%A2=%BD', { charset: 'iso-8859-1' }), { '¢': '½' });
|
|
589
|
+
st.end();
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
var urlEncodedCheckmarkInUtf8 = '%E2%9C%93';
|
|
593
|
+
var urlEncodedOSlashInUtf8 = '%C3%B8';
|
|
594
|
+
var urlEncodedNumCheckmark = '%26%2310003%3B';
|
|
595
|
+
var urlEncodedNumSmiley = '%26%239786%3B';
|
|
596
|
+
|
|
597
|
+
t.test('prefers an utf-8 charset specified by the utf8 sentinel to a default charset of iso-8859-1', function (st) {
|
|
598
|
+
st.deepEqual(qs.parse('utf8=' + urlEncodedCheckmarkInUtf8 + '&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true, charset: 'iso-8859-1' }), { ø: 'ø' });
|
|
599
|
+
st.end();
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
t.test('prefers an iso-8859-1 charset specified by the utf8 sentinel to a default charset of utf-8', function (st) {
|
|
603
|
+
st.deepEqual(qs.parse('utf8=' + urlEncodedNumCheckmark + '&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true, charset: 'utf-8' }), { 'ø': 'ø' });
|
|
604
|
+
st.end();
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
t.test('does not require the utf8 sentinel to be defined before the parameters whose decoding it affects', function (st) {
|
|
608
|
+
st.deepEqual(qs.parse('a=' + urlEncodedOSlashInUtf8 + '&utf8=' + urlEncodedNumCheckmark, { charsetSentinel: true, charset: 'utf-8' }), { a: 'ø' });
|
|
609
|
+
st.end();
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
t.test('should ignore an utf8 sentinel with an unknown value', function (st) {
|
|
613
|
+
st.deepEqual(qs.parse('utf8=foo&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true, charset: 'utf-8' }), { ø: 'ø' });
|
|
614
|
+
st.end();
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
t.test('uses the utf8 sentinel to switch to utf-8 when no default charset is given', function (st) {
|
|
618
|
+
st.deepEqual(qs.parse('utf8=' + urlEncodedCheckmarkInUtf8 + '&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true }), { ø: 'ø' });
|
|
619
|
+
st.end();
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
t.test('uses the utf8 sentinel to switch to iso-8859-1 when no default charset is given', function (st) {
|
|
623
|
+
st.deepEqual(qs.parse('utf8=' + urlEncodedNumCheckmark + '&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true }), { 'ø': 'ø' });
|
|
624
|
+
st.end();
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
t.test('interprets numeric entities in iso-8859-1 when `interpretNumericEntities`', function (st) {
|
|
628
|
+
st.deepEqual(qs.parse('foo=' + urlEncodedNumSmiley, { charset: 'iso-8859-1', interpretNumericEntities: true }), { foo: '☺' });
|
|
629
|
+
st.end();
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
t.test('handles a custom decoder returning `null`, in the `iso-8859-1` charset, when `interpretNumericEntities`', function (st) {
|
|
633
|
+
st.deepEqual(qs.parse('foo=&bar=' + urlEncodedNumSmiley, {
|
|
634
|
+
charset: 'iso-8859-1',
|
|
635
|
+
decoder: function (str, defaultDecoder, charset) {
|
|
636
|
+
return str ? defaultDecoder(str, defaultDecoder, charset) : null;
|
|
637
|
+
},
|
|
638
|
+
interpretNumericEntities: true
|
|
639
|
+
}), { foo: null, bar: '☺' });
|
|
640
|
+
st.end();
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
t.test('does not interpret numeric entities in iso-8859-1 when `interpretNumericEntities` is absent', function (st) {
|
|
644
|
+
st.deepEqual(qs.parse('foo=' + urlEncodedNumSmiley, { charset: 'iso-8859-1' }), { foo: '☺' });
|
|
645
|
+
st.end();
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
t.test('does not interpret numeric entities when the charset is utf-8, even when `interpretNumericEntities`', function (st) {
|
|
649
|
+
st.deepEqual(qs.parse('foo=' + urlEncodedNumSmiley, { charset: 'utf-8', interpretNumericEntities: true }), { foo: '☺' });
|
|
650
|
+
st.end();
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
t.test('does not interpret %uXXXX syntax in iso-8859-1 mode', function (st) {
|
|
654
|
+
st.deepEqual(qs.parse('%u263A=%u263A', { charset: 'iso-8859-1' }), { '%u263A': '%u263A' });
|
|
655
|
+
st.end();
|
|
656
|
+
});
|
|
657
|
+
|
|
648
658
|
t.end();
|
|
649
659
|
});
|
package/test/stringify.js
CHANGED
|
@@ -19,15 +19,6 @@ test('stringify()', function (t) {
|
|
|
19
19
|
st.end();
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
t.test('stringifies falsy values', function (st) {
|
|
23
|
-
st.equal(qs.stringify(undefined), '');
|
|
24
|
-
st.equal(qs.stringify(null), '');
|
|
25
|
-
st.equal(qs.stringify(null, { strictNullHandling: true }), '');
|
|
26
|
-
st.equal(qs.stringify(false), '');
|
|
27
|
-
st.equal(qs.stringify(0), '');
|
|
28
|
-
st.end();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
22
|
t.test('adds query prefix', function (st) {
|
|
32
23
|
st.equal(qs.stringify({ a: 'b' }, { addQueryPrefix: true }), '?a=b');
|
|
33
24
|
st.end();
|
|
@@ -38,13 +29,6 @@ test('stringify()', function (t) {
|
|
|
38
29
|
st.end();
|
|
39
30
|
});
|
|
40
31
|
|
|
41
|
-
t.test('stringifies nested falsy values', function (st) {
|
|
42
|
-
st.equal(qs.stringify({ a: { b: { c: null } } }), 'a%5Bb%5D%5Bc%5D=');
|
|
43
|
-
st.equal(qs.stringify({ a: { b: { c: null } } }, { strictNullHandling: true }), 'a%5Bb%5D%5Bc%5D');
|
|
44
|
-
st.equal(qs.stringify({ a: { b: { c: false } } }), 'a%5Bb%5D%5Bc%5D=false');
|
|
45
|
-
st.end();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
32
|
t.test('stringifies a nested object', function (st) {
|
|
49
33
|
st.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
|
|
50
34
|
st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }), 'a%5Bb%5D%5Bc%5D%5Bd%5D=e');
|
|
@@ -506,12 +490,6 @@ test('stringify()', function (t) {
|
|
|
506
490
|
return String.fromCharCode(buffer.readUInt8(0) + 97);
|
|
507
491
|
}
|
|
508
492
|
}), 'a=b');
|
|
509
|
-
|
|
510
|
-
st.equal(qs.stringify({ a: SaferBuffer.from('a b') }, {
|
|
511
|
-
encoder: function (buffer) {
|
|
512
|
-
return buffer;
|
|
513
|
-
}
|
|
514
|
-
}), 'a=a b');
|
|
515
493
|
st.end();
|
|
516
494
|
});
|
|
517
495
|
|
|
@@ -552,20 +530,17 @@ test('stringify()', function (t) {
|
|
|
552
530
|
t.test('RFC 1738 spaces serialization', function (st) {
|
|
553
531
|
st.equal(qs.stringify({ a: 'b c' }, { format: qs.formats.RFC1738 }), 'a=b+c');
|
|
554
532
|
st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC1738 }), 'a+b=c+d');
|
|
555
|
-
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC1738 }), 'a+b=a+b');
|
|
556
533
|
st.end();
|
|
557
534
|
});
|
|
558
535
|
|
|
559
536
|
t.test('RFC 3986 spaces serialization', function (st) {
|
|
560
537
|
st.equal(qs.stringify({ a: 'b c' }, { format: qs.formats.RFC3986 }), 'a=b%20c');
|
|
561
538
|
st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC3986 }), 'a%20b=c%20d');
|
|
562
|
-
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC3986 }), 'a%20b=a%20b');
|
|
563
539
|
st.end();
|
|
564
540
|
});
|
|
565
541
|
|
|
566
542
|
t.test('Backward compatibility to RFC 3986', function (st) {
|
|
567
543
|
st.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
|
|
568
|
-
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }), 'a%20b=a%20b');
|
|
569
544
|
st.end();
|
|
570
545
|
});
|
|
571
546
|
|
|
@@ -611,6 +586,38 @@ test('stringify()', function (t) {
|
|
|
611
586
|
st.end();
|
|
612
587
|
});
|
|
613
588
|
|
|
589
|
+
t.test('throws if an invalid charset is specified', function (st) {
|
|
590
|
+
st['throws'](function () {
|
|
591
|
+
qs.stringify({ a: 'b' }, { charset: 'foobar' });
|
|
592
|
+
}, new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'));
|
|
593
|
+
st.end();
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
t.test('respects a charset of iso-8859-1', function (st) {
|
|
597
|
+
st.equal(qs.stringify({ æ: 'æ' }, { charset: 'iso-8859-1' }), '%E6=%E6');
|
|
598
|
+
st.end();
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
t.test('encodes unrepresentable chars as numeric entities in iso-8859-1 mode', function (st) {
|
|
602
|
+
st.equal(qs.stringify({ a: '☺' }, { charset: 'iso-8859-1' }), 'a=%26%239786%3B');
|
|
603
|
+
st.end();
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
t.test('respects an explicit charset of utf-8 (the default)', function (st) {
|
|
607
|
+
st.equal(qs.stringify({ a: 'æ' }, { charset: 'utf-8' }), 'a=%C3%A6');
|
|
608
|
+
st.end();
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
t.test('adds the right sentinel when instructed to and the charset is utf-8', function (st) {
|
|
612
|
+
st.equal(qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'utf-8' }), 'utf8=%E2%9C%93&a=%C3%A6');
|
|
613
|
+
st.end();
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
t.test('adds the right sentinel when instructed to and the charset is iso-8859-1', function (st) {
|
|
617
|
+
st.equal(qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' }), 'utf8=%26%2310003%3B&a=%E6');
|
|
618
|
+
st.end();
|
|
619
|
+
});
|
|
620
|
+
|
|
614
621
|
t.test('does not mutate the options argument', function (st) {
|
|
615
622
|
var options = {};
|
|
616
623
|
qs.stringify({}, options);
|