qs 6.0.4 → 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 CHANGED
@@ -4,10 +4,10 @@
4
4
  "extends": "@ljharb",
5
5
 
6
6
  "rules": {
7
- "complexity": [2, 18],
7
+ "complexity": [2, 19],
8
8
  "consistent-return": [1],
9
- "max-params": [2, 8],
10
- "max-statements": [2, 32],
9
+ "max-params": [2, 9],
10
+ "max-statements": [2, 33],
11
11
  "no-extra-parens": [1],
12
12
  "no-continue": [1],
13
13
  "no-magic-numbers": 0,
package/.travis.yml CHANGED
@@ -1,173 +1,69 @@
1
1
  language: node_js
2
- os:
3
- - linux
4
2
  node_js:
5
- - "7.7"
6
- - "6.10"
7
- - "5.12"
8
- - "4.8"
3
+ - "5.3"
4
+ - "5.2"
5
+ - "5.1"
6
+ - "5.0"
7
+ - "4.2"
8
+ - "4.1"
9
+ - "4.0"
9
10
  - "iojs-v3.3"
11
+ - "iojs-v3.2"
12
+ - "iojs-v3.1"
13
+ - "iojs-v3.0"
10
14
  - "iojs-v2.5"
15
+ - "iojs-v2.4"
16
+ - "iojs-v2.3"
17
+ - "iojs-v2.2"
18
+ - "iojs-v2.1"
19
+ - "iojs-v2.0"
11
20
  - "iojs-v1.8"
21
+ - "iojs-v1.7"
22
+ - "iojs-v1.6"
23
+ - "iojs-v1.5"
24
+ - "iojs-v1.4"
25
+ - "iojs-v1.3"
26
+ - "iojs-v1.2"
27
+ - "iojs-v1.1"
28
+ - "iojs-v1.0"
12
29
  - "0.12"
30
+ - "0.11"
13
31
  - "0.10"
32
+ - "0.9"
14
33
  - "0.8"
34
+ - "0.6"
35
+ - "0.4"
15
36
  before_install:
16
- - 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ]; then npm install -g npm@1.3 ; elif [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then case "$(npm --version)" in 1.*) npm install -g npm@1.4.28 ;; 2.*) npm install -g npm@2 ;; esac ; fi'
37
+ - 'if [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then case "$(npm --version)" in 1.*) npm install -g npm@1.4.28 ;; 2.*) npm install -g npm@2 ;; esac ; fi'
17
38
  - 'if [ "${TRAVIS_NODE_VERSION}" != "0.6" ] && [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then npm install -g npm; fi'
18
39
  script:
19
- - 'if [ -n "${PRETEST-}" ]; then npm run pretest ; fi'
20
- - 'if [ -n "${POSTTEST-}" ]; then npm run posttest ; fi'
21
- - 'if [ -n "${COVERAGE-}" ]; then npm run coverage ; fi'
22
- - 'if [ -n "${TEST-}" ]; then npm run tests-only ; fi'
40
+ - 'if [ "${TRAVIS_NODE_VERSION}" != "4.2" ]; then npm run tests-only ; else npm test ; fi'
23
41
  sudo: false
24
- env:
25
- - TEST=true
26
42
  matrix:
27
43
  fast_finish: true
28
- include:
29
- - node_js: "node"
30
- env: PRETEST=true
31
- - node_js: "4"
32
- env: COVERAGE=true
33
- - node_js: "7.6"
34
- env: TEST=true ALLOW_FAILURE=true
35
- - node_js: "7.5"
36
- env: TEST=true ALLOW_FAILURE=true
37
- - node_js: "7.4"
38
- env: TEST=true ALLOW_FAILURE=true
39
- - node_js: "7.3"
40
- env: TEST=true ALLOW_FAILURE=true
41
- - node_js: "7.2"
42
- env: TEST=true ALLOW_FAILURE=true
43
- - node_js: "7.1"
44
- env: TEST=true ALLOW_FAILURE=true
45
- - node_js: "7.0"
46
- env: TEST=true ALLOW_FAILURE=true
47
- - node_js: "6.9"
48
- env: TEST=true ALLOW_FAILURE=true
49
- - node_js: "6.8"
50
- env: TEST=true ALLOW_FAILURE=true
51
- - node_js: "6.7"
52
- env: TEST=true ALLOW_FAILURE=true
53
- - node_js: "6.6"
54
- env: TEST=true ALLOW_FAILURE=true
55
- - node_js: "6.5"
56
- env: TEST=true ALLOW_FAILURE=true
57
- - node_js: "6.4"
58
- env: TEST=true ALLOW_FAILURE=true
59
- - node_js: "6.3"
60
- env: TEST=true ALLOW_FAILURE=true
61
- - node_js: "6.2"
62
- env: TEST=true ALLOW_FAILURE=true
63
- - node_js: "6.1"
64
- env: TEST=true ALLOW_FAILURE=true
65
- - node_js: "6.0"
66
- env: TEST=true ALLOW_FAILURE=true
67
- - node_js: "5.11"
68
- env: TEST=true ALLOW_FAILURE=true
69
- - node_js: "5.10"
70
- env: TEST=true ALLOW_FAILURE=true
71
- - node_js: "5.9"
72
- env: TEST=true ALLOW_FAILURE=true
73
- - node_js: "5.8"
74
- env: TEST=true ALLOW_FAILURE=true
75
- - node_js: "5.7"
76
- env: TEST=true ALLOW_FAILURE=true
77
- - node_js: "5.6"
78
- env: TEST=true ALLOW_FAILURE=true
79
- - node_js: "5.5"
80
- env: TEST=true ALLOW_FAILURE=true
81
- - node_js: "5.4"
82
- env: TEST=true ALLOW_FAILURE=true
83
- - node_js: "5.3"
84
- env: TEST=true ALLOW_FAILURE=true
44
+ allow_failures:
85
45
  - node_js: "5.2"
86
- env: TEST=true ALLOW_FAILURE=true
87
46
  - node_js: "5.1"
88
- env: TEST=true ALLOW_FAILURE=true
89
47
  - node_js: "5.0"
90
- env: TEST=true ALLOW_FAILURE=true
91
- - node_js: "4.7"
92
- env: TEST=true ALLOW_FAILURE=true
93
- - node_js: "4.6"
94
- env: TEST=true ALLOW_FAILURE=true
95
- - node_js: "4.5"
96
- env: TEST=true ALLOW_FAILURE=true
97
- - node_js: "4.4"
98
- env: TEST=true ALLOW_FAILURE=true
99
- - node_js: "4.3"
100
- env: TEST=true ALLOW_FAILURE=true
101
- - node_js: "4.2"
102
- env: TEST=true ALLOW_FAILURE=true
103
48
  - node_js: "4.1"
104
- env: TEST=true ALLOW_FAILURE=true
105
49
  - node_js: "4.0"
106
- env: TEST=true ALLOW_FAILURE=true
107
50
  - node_js: "iojs-v3.2"
108
- env: TEST=true ALLOW_FAILURE=true
109
51
  - node_js: "iojs-v3.1"
110
- env: TEST=true ALLOW_FAILURE=true
111
52
  - node_js: "iojs-v3.0"
112
- env: TEST=true ALLOW_FAILURE=true
113
53
  - node_js: "iojs-v2.4"
114
- env: TEST=true ALLOW_FAILURE=true
115
54
  - node_js: "iojs-v2.3"
116
- env: TEST=true ALLOW_FAILURE=true
117
55
  - node_js: "iojs-v2.2"
118
- env: TEST=true ALLOW_FAILURE=true
119
56
  - node_js: "iojs-v2.1"
120
- env: TEST=true ALLOW_FAILURE=true
121
57
  - node_js: "iojs-v2.0"
122
- env: TEST=true ALLOW_FAILURE=true
123
58
  - node_js: "iojs-v1.7"
124
- env: TEST=true ALLOW_FAILURE=true
125
59
  - node_js: "iojs-v1.6"
126
- env: TEST=true ALLOW_FAILURE=true
127
60
  - node_js: "iojs-v1.5"
128
- env: TEST=true ALLOW_FAILURE=true
129
61
  - node_js: "iojs-v1.4"
130
- env: TEST=true ALLOW_FAILURE=true
131
62
  - node_js: "iojs-v1.3"
132
- env: TEST=true ALLOW_FAILURE=true
133
63
  - node_js: "iojs-v1.2"
134
- env: TEST=true ALLOW_FAILURE=true
135
64
  - node_js: "iojs-v1.1"
136
- env: TEST=true ALLOW_FAILURE=true
137
65
  - node_js: "iojs-v1.0"
138
- env: TEST=true ALLOW_FAILURE=true
139
66
  - node_js: "0.11"
140
- env: TEST=true ALLOW_FAILURE=true
141
67
  - node_js: "0.9"
142
- env: TEST=true ALLOW_FAILURE=true
143
68
  - node_js: "0.6"
144
- env: TEST=true ALLOW_FAILURE=true
145
69
  - node_js: "0.4"
146
- env: TEST=true ALLOW_FAILURE=true
147
- ##- node_js: "7"
148
- #env: TEST=true
149
- #os: osx
150
- #- node_js: "6"
151
- #env: TEST=true
152
- #os: osx
153
- #- node_js: "5"
154
- #env: TEST=true
155
- #os: osx
156
- #- node_js: "4"
157
- #env: TEST=true
158
- #os: osx
159
- #- node_js: "iojs"
160
- #env: TEST=true
161
- #os: osx
162
- #- node_js: "0.12"
163
- #env: TEST=true
164
- #os: osx
165
- #- node_js: "0.10"
166
- #env: TEST=true
167
- #os: osx
168
- #- node_js: "0.8"
169
- #env: TEST=true
170
- #os: osx
171
- allow_failures:
172
- - os: osx
173
- - env: TEST=true ALLOW_FAILURE=true
package/CHANGELOG.md CHANGED
@@ -1,11 +1,6 @@
1
- ## **6.0.4**
2
- - [Fix] follow `allowPrototypes` option during merge (#201, #200)
3
- - [Fix] chmod a-x
4
- - [Fix] support keys starting with brackets (#202, #200)
5
- - [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
6
-
7
- ## **6.0.3**
8
- - [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties
1
+ ## [**6.1.0**](https://github.com/ljharb/qs/issues?milestone=34&state=closed)
2
+ - [New] allowDots option for `stringify` (#151)
3
+ - [Fix] "sort" option should work at a depth of 3 or more (#151)
9
4
  - [Fix] Restore `dist` directory; will be removed in v7 (#148)
10
5
 
11
6
  ## [**6.0.2**](https://github.com/ljharb/qs/issues?milestone=33&state=closed)
package/component.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "qs",
3
3
  "repository": "hapijs/qs",
4
4
  "description": "query-string parser / stringifier with nesting support",
5
- "version": "6.0.4",
5
+ "version": "6.1.0",
6
6
  "keywords": ["querystring", "query", "parser"],
7
7
  "main": "lib/index.js",
8
8
  "scripts": [
package/dist/qs.js CHANGED
@@ -25,8 +25,6 @@ var internals = {
25
25
  allowDots: false
26
26
  };
27
27
 
28
- var has = Object.prototype.hasOwnProperty;
29
-
30
28
  internals.parseValues = function (str, options) {
31
29
  var obj = {};
32
30
  var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
@@ -45,7 +43,7 @@ internals.parseValues = function (str, options) {
45
43
  var key = Utils.decode(part.slice(0, pos));
46
44
  var val = Utils.decode(part.slice(pos + 1));
47
45
 
48
- if (has.call(obj, key)) {
46
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
49
47
  obj[key] = [].concat(obj[key]).concat(val);
50
48
  } else {
51
49
  obj[key] = val;
@@ -69,7 +67,7 @@ internals.parseObject = function (chain, val, options) {
69
67
  obj = obj.concat(internals.parseObject(chain, val, options));
70
68
  } else {
71
69
  obj = options.plainObjects ? Object.create(null) : {};
72
- var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
70
+ var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root;
73
71
  var index = parseInt(cleanRoot, 10);
74
72
  if (
75
73
  !isNaN(index) &&
@@ -98,27 +96,26 @@ internals.parseKeys = function (givenKey, val, options) {
98
96
 
99
97
  // The regex chunks
100
98
 
101
- var brackets = /(\[[^[\]]*])/;
102
- var child = /(\[[^[\]]*])/g;
99
+ var parent = /^([^\[\]]*)/;
100
+ var child = /(\[[^\[\]]*\])/g;
103
101
 
104
102
  // Get the parent
105
103
 
106
- var segment = brackets.exec(key);
107
- var parent = segment ? key.slice(0, segment.index) : key;
104
+ var segment = parent.exec(key);
108
105
 
109
106
  // Stash the parent if it exists
110
107
 
111
108
  var keys = [];
112
- if (parent) {
109
+ if (segment[1]) {
113
110
  // If we aren't using plain objects, optionally prefix keys
114
111
  // that would overwrite object prototype properties
115
- if (!options.plainObjects && has.call(Object.prototype, parent)) {
112
+ if (!options.plainObjects && Object.prototype.hasOwnProperty(segment[1])) {
116
113
  if (!options.allowPrototypes) {
117
114
  return;
118
115
  }
119
116
  }
120
117
 
121
- keys.push(parent);
118
+ keys.push(segment[1]);
122
119
  }
123
120
 
124
121
  // Loop through children appending to the array until we hit depth
@@ -126,9 +123,9 @@ internals.parseKeys = function (givenKey, val, options) {
126
123
  var i = 0;
127
124
  while ((segment = child.exec(key)) !== null && i < options.depth) {
128
125
  i += 1;
129
- if (!options.plainObjects && has.call(Object.prototype, segment[1].slice(1, -1))) {
126
+ if (!options.plainObjects && Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) {
130
127
  if (!options.allowPrototypes) {
131
- return;
128
+ continue;
132
129
  }
133
130
  }
134
131
  keys.push(segment[1]);
@@ -201,7 +198,7 @@ var internals = {
201
198
  encode: true
202
199
  };
203
200
 
204
- internals.stringify = function (object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort) {
201
+ internals.stringify = function (object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort, allowDots) {
205
202
  var obj = object;
206
203
  if (typeof filter === 'function') {
207
204
  obj = filter(prefix, obj);
@@ -246,9 +243,9 @@ internals.stringify = function (object, prefix, generateArrayPrefix, strictNullH
246
243
  }
247
244
 
248
245
  if (Array.isArray(obj)) {
249
- values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
246
+ values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort, allowDots));
250
247
  } else {
251
- values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
248
+ values = values.concat(internals.stringify(obj[key], prefix + (allowDots ? '.' + key : '[' + key + ']'), generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort, allowDots));
252
249
  }
253
250
  }
254
251
 
@@ -263,6 +260,7 @@ module.exports = function (object, opts) {
263
260
  var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : internals.skipNulls;
264
261
  var encode = typeof options.encode === 'boolean' ? options.encode : internals.encode;
265
262
  var sort = typeof options.sort === 'function' ? options.sort : null;
263
+ var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
266
264
  var objKeys;
267
265
  var filter;
268
266
  if (typeof options.filter === 'function') {
@@ -304,7 +302,7 @@ module.exports = function (object, opts) {
304
302
  continue;
305
303
  }
306
304
 
307
- keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort));
305
+ keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort, allowDots));
308
306
  }
309
307
 
310
308
  return keys.join(delimiter);
@@ -322,8 +320,6 @@ var hexTable = (function () {
322
320
  return array;
323
321
  }());
324
322
 
325
- var has = Object.prototype.hasOwnProperty;
326
-
327
323
  exports.arrayToObject = function (source, options) {
328
324
  var obj = options.plainObjects ? Object.create(null) : {};
329
325
  for (var i = 0; i < source.length; ++i) {
@@ -344,9 +340,7 @@ exports.merge = function (target, source, options) {
344
340
  if (Array.isArray(target)) {
345
341
  target.push(source);
346
342
  } else if (typeof target === 'object') {
347
- if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
348
- target[source] = true;
349
- }
343
+ target[source] = true;
350
344
  } else {
351
345
  return [target, source];
352
346
  }
@@ -366,7 +360,7 @@ exports.merge = function (target, source, options) {
366
360
  return Object.keys(source).reduce(function (acc, key) {
367
361
  var value = source[key];
368
362
 
369
- if (has.call(acc, key)) {
363
+ if (Object.prototype.hasOwnProperty.call(acc, key)) {
370
364
  acc[key] = exports.merge(acc[key], value, options);
371
365
  } else {
372
366
  acc[key] = value;
package/lib/index.js CHANGED
File without changes
package/lib/parse.js CHANGED
@@ -13,8 +13,6 @@ var internals = {
13
13
  allowDots: false
14
14
  };
15
15
 
16
- var has = Object.prototype.hasOwnProperty;
17
-
18
16
  internals.parseValues = function (str, options) {
19
17
  var obj = {};
20
18
  var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
@@ -33,7 +31,7 @@ internals.parseValues = function (str, options) {
33
31
  var key = Utils.decode(part.slice(0, pos));
34
32
  var val = Utils.decode(part.slice(pos + 1));
35
33
 
36
- if (has.call(obj, key)) {
34
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
37
35
  obj[key] = [].concat(obj[key]).concat(val);
38
36
  } else {
39
37
  obj[key] = val;
@@ -57,7 +55,7 @@ internals.parseObject = function (chain, val, options) {
57
55
  obj = obj.concat(internals.parseObject(chain, val, options));
58
56
  } else {
59
57
  obj = options.plainObjects ? Object.create(null) : {};
60
- var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
58
+ var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root;
61
59
  var index = parseInt(cleanRoot, 10);
62
60
  if (
63
61
  !isNaN(index) &&
@@ -86,27 +84,26 @@ internals.parseKeys = function (givenKey, val, options) {
86
84
 
87
85
  // The regex chunks
88
86
 
89
- var brackets = /(\[[^[\]]*])/;
90
- var child = /(\[[^[\]]*])/g;
87
+ var parent = /^([^\[\]]*)/;
88
+ var child = /(\[[^\[\]]*\])/g;
91
89
 
92
90
  // Get the parent
93
91
 
94
- var segment = brackets.exec(key);
95
- var parent = segment ? key.slice(0, segment.index) : key;
92
+ var segment = parent.exec(key);
96
93
 
97
94
  // Stash the parent if it exists
98
95
 
99
96
  var keys = [];
100
- if (parent) {
97
+ if (segment[1]) {
101
98
  // If we aren't using plain objects, optionally prefix keys
102
99
  // that would overwrite object prototype properties
103
- if (!options.plainObjects && has.call(Object.prototype, parent)) {
100
+ if (!options.plainObjects && Object.prototype.hasOwnProperty(segment[1])) {
104
101
  if (!options.allowPrototypes) {
105
102
  return;
106
103
  }
107
104
  }
108
105
 
109
- keys.push(parent);
106
+ keys.push(segment[1]);
110
107
  }
111
108
 
112
109
  // Loop through children appending to the array until we hit depth
@@ -114,9 +111,9 @@ internals.parseKeys = function (givenKey, val, options) {
114
111
  var i = 0;
115
112
  while ((segment = child.exec(key)) !== null && i < options.depth) {
116
113
  i += 1;
117
- if (!options.plainObjects && has.call(Object.prototype, segment[1].slice(1, -1))) {
114
+ if (!options.plainObjects && Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) {
118
115
  if (!options.allowPrototypes) {
119
- return;
116
+ continue;
120
117
  }
121
118
  }
122
119
  keys.push(segment[1]);
package/lib/stringify.js CHANGED
@@ -20,7 +20,7 @@ var internals = {
20
20
  encode: true
21
21
  };
22
22
 
23
- internals.stringify = function (object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort) {
23
+ internals.stringify = function (object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort, allowDots) {
24
24
  var obj = object;
25
25
  if (typeof filter === 'function') {
26
26
  obj = filter(prefix, obj);
@@ -65,9 +65,9 @@ internals.stringify = function (object, prefix, generateArrayPrefix, strictNullH
65
65
  }
66
66
 
67
67
  if (Array.isArray(obj)) {
68
- values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
68
+ values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort, allowDots));
69
69
  } else {
70
- values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
70
+ values = values.concat(internals.stringify(obj[key], prefix + (allowDots ? '.' + key : '[' + key + ']'), generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort, allowDots));
71
71
  }
72
72
  }
73
73
 
@@ -82,6 +82,7 @@ module.exports = function (object, opts) {
82
82
  var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : internals.skipNulls;
83
83
  var encode = typeof options.encode === 'boolean' ? options.encode : internals.encode;
84
84
  var sort = typeof options.sort === 'function' ? options.sort : null;
85
+ var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
85
86
  var objKeys;
86
87
  var filter;
87
88
  if (typeof options.filter === 'function') {
@@ -123,7 +124,7 @@ module.exports = function (object, opts) {
123
124
  continue;
124
125
  }
125
126
 
126
- keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort));
127
+ keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort, allowDots));
127
128
  }
128
129
 
129
130
  return keys.join(delimiter);
package/lib/utils.js CHANGED
@@ -9,8 +9,6 @@ var hexTable = (function () {
9
9
  return array;
10
10
  }());
11
11
 
12
- var has = Object.prototype.hasOwnProperty;
13
-
14
12
  exports.arrayToObject = function (source, options) {
15
13
  var obj = options.plainObjects ? Object.create(null) : {};
16
14
  for (var i = 0; i < source.length; ++i) {
@@ -31,9 +29,7 @@ exports.merge = function (target, source, options) {
31
29
  if (Array.isArray(target)) {
32
30
  target.push(source);
33
31
  } else if (typeof target === 'object') {
34
- if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
35
- target[source] = true;
36
- }
32
+ target[source] = true;
37
33
  } else {
38
34
  return [target, source];
39
35
  }
@@ -53,7 +49,7 @@ exports.merge = function (target, source, options) {
53
49
  return Object.keys(source).reduce(function (acc, key) {
54
50
  var value = source[key];
55
51
 
56
- if (has.call(acc, key)) {
52
+ if (Object.prototype.hasOwnProperty.call(acc, key)) {
57
53
  acc[key] = exports.merge(acc[key], value, options);
58
54
  } else {
59
55
  acc[key] = value;
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.0.4",
5
+ "version": "6.1.0",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/ljharb/qs.git"
@@ -34,8 +34,7 @@
34
34
  "evalmd": "^0.0.16"
35
35
  },
36
36
  "scripts": {
37
- "pretest": "npm run lint && npm run readme",
38
- "test": "npm run coverage",
37
+ "test": "parallelshell 'npm run readme' 'npm run lint' 'npm run coverage'",
39
38
  "tests-only": "node test",
40
39
  "readme": "evalmd README.md",
41
40
  "lint": "eslint lib/*.js text/*.js",
package/test/parse.js CHANGED
@@ -120,11 +120,8 @@ test('parse()', function (t) {
120
120
  st.deepEqual(qs.parse('foo[]=bar&foo[bad]=baz'), { foo: { '0': 'bar', bad: 'baz' } });
121
121
  st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar&foo[]=foo'), { foo: { bad: 'baz', '0': 'bar', '1': 'foo' } });
122
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
-
124
- st.deepEqual(qs.parse('a[]=b&a[t]=u&a[hasOwnProperty]=c', { allowPrototypes: false }), { a: { 0: 'b', t: 'u' } });
125
- st.deepEqual(qs.parse('a[]=b&a[t]=u&a[hasOwnProperty]=c', { allowPrototypes: true }), { a: { 0: 'b', t: 'u', hasOwnProperty: 'c' } });
126
- st.deepEqual(qs.parse('a[]=b&a[hasOwnProperty]=c&a[x]=y', { allowPrototypes: false }), { a: { 0: 'b', x: 'y' } });
127
- st.deepEqual(qs.parse('a[]=b&a[hasOwnProperty]=c&a[x]=y', { allowPrototypes: true }), { a: { 0: 'b', hasOwnProperty: 'c', x: 'y' } });
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' } });
128
125
  st.end();
129
126
  });
130
127
 
@@ -142,6 +139,8 @@ test('parse()', function (t) {
142
139
  st.end();
143
140
  });
144
141
 
142
+ t.deepEqual(qs.parse('a[b]=c&a=d'), { a: { b: 'c', d: true } }, 'can add keys to objects');
143
+
145
144
  t.test('correctly prunes undefined values when converting an array to an object', function (st) {
146
145
  st.deepEqual(qs.parse('a[2]=b&a[99999999]=c'), { a: { '2': 'b', '99999999': 'c' } });
147
146
  st.end();
@@ -371,75 +370,13 @@ test('parse()', function (t) {
371
370
  st.end();
372
371
  });
373
372
 
374
- t.test('does not allow overwriting prototype properties', function (st) {
375
- st.deepEqual(qs.parse('a[hasOwnProperty]=b', { allowPrototypes: false }), {});
376
- st.deepEqual(qs.parse('hasOwnProperty=b', { allowPrototypes: false }), {});
377
-
378
- st.deepEqual(
379
- qs.parse('toString', { allowPrototypes: false }),
380
- {},
381
- 'bare "toString" results in {}'
382
- );
383
-
384
- st.end();
385
- });
386
-
387
373
  t.test('can allow overwriting prototype properties', function (st) {
388
- st.deepEqual(qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true }), { a: { hasOwnProperty: 'b' } });
389
- st.deepEqual(qs.parse('hasOwnProperty=b', { allowPrototypes: true }), { hasOwnProperty: 'b' });
390
-
391
- st.deepEqual(
392
- qs.parse('toString', { allowPrototypes: true }),
393
- { toString: '' },
394
- 'bare "toString" results in { toString: "" }'
395
- );
396
-
397
- st.end();
398
- });
399
-
400
- t.test('params starting with a closing bracket', function (st) {
401
- st.deepEqual(qs.parse(']=toString'), { ']': 'toString' });
402
- st.deepEqual(qs.parse(']]=toString'), { ']]': 'toString' });
403
- st.deepEqual(qs.parse(']hello]=toString'), { ']hello]': 'toString' });
404
- st.end();
405
- });
406
-
407
- t.test('params starting with a starting bracket', function (st) {
408
- st.deepEqual(qs.parse('[=toString'), { '[': 'toString' });
409
- st.deepEqual(qs.parse('[[=toString'), { '[[': 'toString' });
410
- st.deepEqual(qs.parse('[hello[=toString'), { '[hello[': 'toString' });
411
- st.end();
412
- });
413
-
414
- t.test('add keys to objects', function (st) {
415
- st.deepEqual(
416
- qs.parse('a[b]=c&a=d'),
417
- { a: { b: 'c', d: true } },
418
- 'can add keys to objects'
419
- );
420
-
421
- st.deepEqual(
422
- qs.parse('a[b]=c&a=toString'),
423
- { a: { b: 'c' } },
424
- 'can not overwrite prototype'
425
- );
426
-
427
- st.deepEqual(
428
- qs.parse('a[b]=c&a=toString', { allowPrototypes: true }),
429
- { a: { b: 'c', toString: true } },
430
- 'can overwrite prototype with allowPrototypes true'
431
- );
432
-
433
- st.deepEqual(
434
- qs.parse('a[b]=c&a=toString', { plainObjects: true }),
435
- { a: { b: 'c', toString: true } },
436
- 'can overwrite prototype with plainObjects true'
437
- );
438
-
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 });
439
376
  st.end();
440
377
  });
441
378
 
442
- t.test('can return null objects', { skip: !Object.create }, function (st) {
379
+ t.test('can return plain objects', function (st) {
443
380
  var expected = Object.create(null);
444
381
  expected.a = Object.create(null);
445
382
  expected.a.b = 'c';
package/test/stringify.js CHANGED
@@ -21,6 +21,12 @@ test('stringify()', function (t) {
21
21
  st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }), 'a%5Bb%5D%5Bc%5D%5Bd%5D=e');
22
22
  st.end();
23
23
  });
24
+
25
+ t.test('stringifies a nested object with dots notation', function (st) {
26
+ st.equal(qs.stringify({ a: { b: 'c' } }, { allowDots: true }), 'a.b=c');
27
+ st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }, { allowDots: true }), 'a.b.c.d=e');
28
+ st.end();
29
+ });
24
30
 
25
31
  t.test('stringifies an array value', function (st) {
26
32
  st.equal(qs.stringify({ a: ['b', 'c', 'd'] }), 'a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d');
@@ -47,12 +53,23 @@ test('stringify()', function (t) {
47
53
  st.equal(qs.stringify({ a: { b: ['c', 'd'] } }), 'a%5Bb%5D%5B0%5D=c&a%5Bb%5D%5B1%5D=d');
48
54
  st.end();
49
55
  });
56
+
57
+ t.test('stringifies a nested array value with dots notation', function (st) {
58
+ st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { allowDots: true, encode: false }), 'a.b[0]=c&a.b[1]=d');
59
+ st.end();
60
+ });
50
61
 
51
62
  t.test('stringifies an object inside an array', function (st) {
52
63
  st.equal(qs.stringify({ a: [{ b: 'c' }] }), 'a%5B0%5D%5Bb%5D=c');
53
64
  st.equal(qs.stringify({ a: [{ b: { c: [1] } }] }), 'a%5B0%5D%5Bb%5D%5Bc%5D%5B0%5D=1');
54
65
  st.end();
55
66
  });
67
+
68
+ t.test('stringifies an object inside an array with dots notation', function (st) {
69
+ st.equal(qs.stringify({ a: [{ b: 'c' }] }, { allowDots: true, encode: false }), 'a[0].b=c');
70
+ st.equal(qs.stringify({ a: [{ b: { c: [1] } }] }, { allowDots: true, encode: false }), 'a[0].b.c[0]=1');
71
+ st.end();
72
+ });
56
73
 
57
74
  t.test('does not omit object keys when indices = false', function (st) {
58
75
  st.equal(qs.stringify({ a: [{ b: 'c' }] }, { indices: false }), 'a%5Bb%5D=c');
@@ -232,4 +249,11 @@ test('stringify()', function (t) {
232
249
  st.equal(qs.stringify({ a: 'c', z: { j: 'a', i: 'b' }, b: 'f' }, { sort: sort }), 'a=c&b=f&z%5Bi%5D=b&z%5Bj%5D=a');
233
250
  st.end();
234
251
  });
252
+
253
+ t.test('can sort the keys at depth 3 or more too', function (st) {
254
+ var sort = function (a, b) { return a.localeCompare(b); };
255
+ st.equal(qs.stringify({ a: 'a', z: { zj: {zjb: 'zjb', zja: 'zja'}, zi: {zib: 'zib', zia: 'zia'} }, b: 'b' }, { sort: sort, encode: false }), 'a=a&b=b&z[zi][zia]=zia&z[zi][zib]=zib&z[zj][zja]=zja&z[zj][zjb]=zjb');
256
+ st.equal(qs.stringify({ a: 'a', z: { zj: {zjb: 'zjb', zja: 'zja'}, zi: {zib: 'zib', zia: 'zia'} }, b: 'b' }, { sort: null, encode: false }), 'a=a&z[zj][zjb]=zjb&z[zj][zja]=zja&z[zi][zib]=zib&z[zi][zia]=zia&b=b');
257
+ st.end();
258
+ });
235
259
  });
package/test/utils.js CHANGED
File without changes