qs
Advanced tools
Comparing version 6.3.2 to 6.3.3
@@ -0,1 +1,21 @@ | ||
## **6.3.3** | ||
- [Fix] `parse`: ignore `__proto__` keys (#428) | ||
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value | ||
- [Fix] `utils.merge`: avoid a crash with a null target and an array source | ||
- [Fix]` `utils.merge`: avoid a crash with a null target and a truthy non-array source | ||
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279) | ||
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided | ||
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]` | ||
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427) | ||
- [Refactor] use cached `Array.isArray` | ||
- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269) | ||
- [Docs] Clarify the need for "arrayLimit" option | ||
- [meta] fix README.md (#399) | ||
- [meta] Clean up license text so it’s properly detected as BSD-3-Clause | ||
- [meta] add FUNDING.yml | ||
- [actions] backport actions from main | ||
- [Tests] use `safer-buffer` instead of `Buffer` constructor | ||
- [Tests] remove nonexistent tape option | ||
- [Dev Deps] backport from main | ||
## **6.3.2** | ||
@@ -2,0 +22,0 @@ - [Fix] follow `allowPrototypes` option during merge (#201, #200) |
@@ -1,2 +0,2 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | ||
'use strict'; | ||
@@ -14,3 +14,3 @@ | ||
RFC3986: function (value) { | ||
return value; | ||
return String(value); | ||
} | ||
@@ -88,3 +88,3 @@ }, | ||
var obj; | ||
if (root === '[]') { | ||
if (root === '[]' && options.parseArrays) { | ||
obj = []; | ||
@@ -96,12 +96,14 @@ obj = obj.concat(parseObject(chain, val, options)); | ||
var index = parseInt(cleanRoot, 10); | ||
if ( | ||
!isNaN(index) && | ||
root !== cleanRoot && | ||
String(index) === cleanRoot && | ||
index >= 0 && | ||
(options.parseArrays && index <= options.arrayLimit) | ||
if (!options.parseArrays && cleanRoot === '') { | ||
obj = { 0: val }; | ||
} else if ( | ||
!isNaN(index) | ||
&& root !== cleanRoot | ||
&& String(index) === cleanRoot | ||
&& index >= 0 | ||
&& (options.parseArrays && index <= options.arrayLimit) | ||
) { | ||
obj = []; | ||
obj[index] = parseObject(chain, val, options); | ||
} else { | ||
} else if (cleanRoot !== '__proto__') { | ||
obj[cleanRoot] = parseObject(chain, val, options); | ||
@@ -136,4 +138,3 @@ } | ||
if (parent) { | ||
// If we aren't using plain objects, optionally prefix keys | ||
// that would overwrite object prototype properties | ||
// If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties | ||
if (!options.plainObjects && has.call(Object.prototype, parent)) { | ||
@@ -214,9 +215,9 @@ if (!options.allowPrototypes) { | ||
var arrayPrefixGenerators = { | ||
brackets: function brackets(prefix) { // eslint-disable-line func-name-matching | ||
brackets: function brackets(prefix) { | ||
return prefix + '[]'; | ||
}, | ||
indices: function indices(prefix, key) { // eslint-disable-line func-name-matching | ||
indices: function indices(prefix, key) { | ||
return prefix + '[' + key + ']'; | ||
}, | ||
repeat: function repeat(prefix) { // eslint-disable-line func-name-matching | ||
repeat: function repeat(prefix) { | ||
return prefix; | ||
@@ -226,2 +227,8 @@ } | ||
var isArray = Array.isArray; | ||
var push = Array.prototype.push; | ||
var pushToArray = function (arr, valueOrArray) { | ||
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]); | ||
}; | ||
var toISO = Date.prototype.toISOString; | ||
@@ -233,3 +240,3 @@ | ||
encoder: utils.encode, | ||
serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching | ||
serializeDate: function serializeDate(date) { | ||
return toISO.call(date); | ||
@@ -241,3 +248,3 @@ }, | ||
var stringify = function stringify( // eslint-disable-line func-name-matching | ||
var stringify = function stringify( | ||
object, | ||
@@ -260,3 +267,5 @@ prefix, | ||
obj = serializeDate(obj); | ||
} else if (obj === null) { | ||
} | ||
if (obj === null) { | ||
if (strictNullHandling) { | ||
@@ -283,3 +292,3 @@ return encoder ? encoder(prefix) : prefix; | ||
var objKeys; | ||
if (Array.isArray(filter)) { | ||
if (isArray(filter)) { | ||
objKeys = filter; | ||
@@ -298,4 +307,4 @@ } else { | ||
if (Array.isArray(obj)) { | ||
values = values.concat(stringify( | ||
if (isArray(obj)) { | ||
pushToArray(values, stringify( | ||
obj[key], | ||
@@ -314,3 +323,3 @@ generateArrayPrefix(prefix, key), | ||
} else { | ||
values = values.concat(stringify( | ||
pushToArray(values, stringify( | ||
obj[key], | ||
@@ -338,3 +347,3 @@ prefix + (allowDots ? '.' + key : '[' + key + ']'), | ||
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') { | ||
if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') { | ||
throw new TypeError('Encoder has to be a function.'); | ||
@@ -347,3 +356,3 @@ } | ||
var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode; | ||
var encoder = encode ? (typeof options.encoder === 'function' ? options.encoder : defaults.encoder) : null; | ||
var encoder = encode ? typeof options.encoder === 'function' ? options.encoder : defaults.encoder : null; | ||
var sort = typeof options.sort === 'function' ? options.sort : null; | ||
@@ -353,3 +362,3 @@ var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots; | ||
if (typeof options.format === 'undefined') { | ||
options.format = formats.default; | ||
options.format = formats['default']; | ||
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) { | ||
@@ -365,3 +374,3 @@ throw new TypeError('Unknown format option provided.'); | ||
obj = filter('', obj); | ||
} else if (Array.isArray(options.filter)) { | ||
} else if (isArray(options.filter)) { | ||
filter = options.filter; | ||
@@ -402,4 +411,3 @@ objKeys = filter; | ||
} | ||
keys = keys.concat(stringify( | ||
pushToArray(keys, stringify( | ||
obj[key], | ||
@@ -455,4 +463,4 @@ key, | ||
target.push(source); | ||
} else if (typeof target === 'object') { | ||
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) { | ||
} else if (target && typeof target === 'object') { | ||
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) { | ||
target[source] = true; | ||
@@ -467,3 +475,3 @@ } | ||
if (typeof target !== 'object') { | ||
if (!target || typeof target !== 'object') { | ||
return [target].concat(source); | ||
@@ -526,9 +534,9 @@ } | ||
if ( | ||
c === 0x2D || // - | ||
c === 0x2E || // . | ||
c === 0x5F || // _ | ||
c === 0x7E || // ~ | ||
(c >= 0x30 && c <= 0x39) || // 0-9 | ||
(c >= 0x41 && c <= 0x5A) || // a-z | ||
(c >= 0x61 && c <= 0x7A) // A-Z | ||
c === 0x2D // - | ||
|| c === 0x2E // . | ||
|| c === 0x5F // _ | ||
|| c === 0x7E // ~ | ||
|| (c >= 0x30 && c <= 0x39) // 0-9 | ||
|| (c >= 0x41 && c <= 0x5A) // a-z | ||
|| (c >= 0x61 && c <= 0x7A) // A-Z | ||
) { | ||
@@ -556,3 +564,7 @@ out += string.charAt(i); | ||
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF)); | ||
out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]; // eslint-disable-line max-len | ||
/* eslint operator-linebreak: [2, "before"] */ | ||
out += hexTable[0xF0 | (c >> 18)] | ||
+ hexTable[0x80 | ((c >> 12) & 0x3F)] | ||
+ hexTable[0x80 | ((c >> 6) & 0x3F)] | ||
+ hexTable[0x80 | (c & 0x3F)]; | ||
} | ||
@@ -611,2 +623,2 @@ | ||
},{}]},{},[2])(2) | ||
}); | ||
}); |
@@ -13,3 +13,3 @@ 'use strict'; | ||
RFC3986: function (value) { | ||
return value; | ||
return String(value); | ||
} | ||
@@ -16,0 +16,0 @@ }, |
@@ -53,3 +53,3 @@ 'use strict'; | ||
var obj; | ||
if (root === '[]') { | ||
if (root === '[]' && options.parseArrays) { | ||
obj = []; | ||
@@ -61,12 +61,14 @@ obj = obj.concat(parseObject(chain, val, options)); | ||
var index = parseInt(cleanRoot, 10); | ||
if ( | ||
!isNaN(index) && | ||
root !== cleanRoot && | ||
String(index) === cleanRoot && | ||
index >= 0 && | ||
(options.parseArrays && index <= options.arrayLimit) | ||
if (!options.parseArrays && cleanRoot === '') { | ||
obj = { 0: val }; | ||
} else if ( | ||
!isNaN(index) | ||
&& root !== cleanRoot | ||
&& String(index) === cleanRoot | ||
&& index >= 0 | ||
&& (options.parseArrays && index <= options.arrayLimit) | ||
) { | ||
obj = []; | ||
obj[index] = parseObject(chain, val, options); | ||
} else { | ||
} else if (cleanRoot !== '__proto__') { | ||
obj[cleanRoot] = parseObject(chain, val, options); | ||
@@ -101,4 +103,3 @@ } | ||
if (parent) { | ||
// If we aren't using plain objects, optionally prefix keys | ||
// that would overwrite object prototype properties | ||
// If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties | ||
if (!options.plainObjects && has.call(Object.prototype, parent)) { | ||
@@ -105,0 +106,0 @@ if (!options.allowPrototypes) { |
@@ -7,9 +7,9 @@ 'use strict'; | ||
var arrayPrefixGenerators = { | ||
brackets: function brackets(prefix) { // eslint-disable-line func-name-matching | ||
brackets: function brackets(prefix) { | ||
return prefix + '[]'; | ||
}, | ||
indices: function indices(prefix, key) { // eslint-disable-line func-name-matching | ||
indices: function indices(prefix, key) { | ||
return prefix + '[' + key + ']'; | ||
}, | ||
repeat: function repeat(prefix) { // eslint-disable-line func-name-matching | ||
repeat: function repeat(prefix) { | ||
return prefix; | ||
@@ -19,2 +19,8 @@ } | ||
var isArray = Array.isArray; | ||
var push = Array.prototype.push; | ||
var pushToArray = function (arr, valueOrArray) { | ||
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]); | ||
}; | ||
var toISO = Date.prototype.toISOString; | ||
@@ -26,3 +32,3 @@ | ||
encoder: utils.encode, | ||
serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching | ||
serializeDate: function serializeDate(date) { | ||
return toISO.call(date); | ||
@@ -34,3 +40,3 @@ }, | ||
var stringify = function stringify( // eslint-disable-line func-name-matching | ||
var stringify = function stringify( | ||
object, | ||
@@ -53,3 +59,5 @@ prefix, | ||
obj = serializeDate(obj); | ||
} else if (obj === null) { | ||
} | ||
if (obj === null) { | ||
if (strictNullHandling) { | ||
@@ -76,3 +84,3 @@ return encoder ? encoder(prefix) : prefix; | ||
var objKeys; | ||
if (Array.isArray(filter)) { | ||
if (isArray(filter)) { | ||
objKeys = filter; | ||
@@ -91,4 +99,4 @@ } else { | ||
if (Array.isArray(obj)) { | ||
values = values.concat(stringify( | ||
if (isArray(obj)) { | ||
pushToArray(values, stringify( | ||
obj[key], | ||
@@ -107,3 +115,3 @@ generateArrayPrefix(prefix, key), | ||
} else { | ||
values = values.concat(stringify( | ||
pushToArray(values, stringify( | ||
obj[key], | ||
@@ -131,3 +139,3 @@ prefix + (allowDots ? '.' + key : '[' + key + ']'), | ||
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') { | ||
if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') { | ||
throw new TypeError('Encoder has to be a function.'); | ||
@@ -140,3 +148,3 @@ } | ||
var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode; | ||
var encoder = encode ? (typeof options.encoder === 'function' ? options.encoder : defaults.encoder) : null; | ||
var encoder = encode ? typeof options.encoder === 'function' ? options.encoder : defaults.encoder : null; | ||
var sort = typeof options.sort === 'function' ? options.sort : null; | ||
@@ -146,3 +154,3 @@ var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots; | ||
if (typeof options.format === 'undefined') { | ||
options.format = formats.default; | ||
options.format = formats['default']; | ||
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) { | ||
@@ -158,3 +166,3 @@ throw new TypeError('Unknown format option provided.'); | ||
obj = filter('', obj); | ||
} else if (Array.isArray(options.filter)) { | ||
} else if (isArray(options.filter)) { | ||
filter = options.filter; | ||
@@ -195,4 +203,3 @@ objKeys = filter; | ||
} | ||
keys = keys.concat(stringify( | ||
pushToArray(keys, stringify( | ||
obj[key], | ||
@@ -199,0 +206,0 @@ key, |
@@ -33,4 +33,4 @@ 'use strict'; | ||
target.push(source); | ||
} else if (typeof target === 'object') { | ||
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) { | ||
} else if (target && typeof target === 'object') { | ||
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) { | ||
target[source] = true; | ||
@@ -45,3 +45,3 @@ } | ||
if (typeof target !== 'object') { | ||
if (!target || typeof target !== 'object') { | ||
return [target].concat(source); | ||
@@ -104,9 +104,9 @@ } | ||
if ( | ||
c === 0x2D || // - | ||
c === 0x2E || // . | ||
c === 0x5F || // _ | ||
c === 0x7E || // ~ | ||
(c >= 0x30 && c <= 0x39) || // 0-9 | ||
(c >= 0x41 && c <= 0x5A) || // a-z | ||
(c >= 0x61 && c <= 0x7A) // A-Z | ||
c === 0x2D // - | ||
|| c === 0x2E // . | ||
|| c === 0x5F // _ | ||
|| c === 0x7E // ~ | ||
|| (c >= 0x30 && c <= 0x39) // 0-9 | ||
|| (c >= 0x41 && c <= 0x5A) // a-z | ||
|| (c >= 0x61 && c <= 0x7A) // A-Z | ||
) { | ||
@@ -134,3 +134,7 @@ out += string.charAt(i); | ||
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF)); | ||
out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]; // eslint-disable-line max-len | ||
/* eslint operator-linebreak: [2, "before"] */ | ||
out += hexTable[0xF0 | (c >> 18)] | ||
+ hexTable[0x80 | ((c >> 12) & 0x3F)] | ||
+ hexTable[0x80 | ((c >> 6) & 0x3F)] | ||
+ hexTable[0x80 | (c & 0x3F)]; | ||
} | ||
@@ -137,0 +141,0 @@ |
100
package.json
{ | ||
"name": "qs", | ||
"description": "A querystring parser that supports nesting and arrays, with a depth limit", | ||
"homepage": "https://github.com/ljharb/qs", | ||
"version": "6.3.2", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/ljharb/qs.git" | ||
}, | ||
"main": "lib/index.js", | ||
"contributors": [ | ||
{ | ||
"name": "Jordan Harband", | ||
"email": "ljharb@gmail.com", | ||
"url": "http://ljharb.codes" | ||
} | ||
], | ||
"keywords": [ | ||
"querystring", | ||
"qs" | ||
], | ||
"engines": { | ||
"node": ">=0.6" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@ljharb/eslint-config": "^11.0.0", | ||
"browserify": "^14.1.0", | ||
"covert": "^1.1.0", | ||
"eslint": "^3.17.0", | ||
"evalmd": "^0.0.17", | ||
"iconv-lite": "^0.4.15", | ||
"mkdirp": "^0.5.1", | ||
"parallelshell": "^2.0.0", | ||
"qs-iconv": "^1.0.4", | ||
"safe-publish-latest": "^1.1.1", | ||
"tape": "^4.6.3" | ||
}, | ||
"scripts": { | ||
"prepublish": "safe-publish-latest && npm run dist", | ||
"pretest": "npm run --silent readme && npm run --silent lint", | ||
"test": "npm run --silent coverage", | ||
"tests-only": "node test", | ||
"readme": "evalmd README.md", | ||
"lint": "eslint lib/*.js test/*.js", | ||
"coverage": "covert test", | ||
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js" | ||
}, | ||
"license": "BSD-3-Clause" | ||
"name": "qs", | ||
"description": "A querystring parser that supports nesting and arrays, with a depth limit", | ||
"homepage": "https://github.com/ljharb/qs", | ||
"version": "6.3.3", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/ljharb/qs.git" | ||
}, | ||
"main": "lib/index.js", | ||
"contributors": [ | ||
{ | ||
"name": "Jordan Harband", | ||
"email": "ljharb@gmail.com", | ||
"url": "http://ljharb.codes" | ||
} | ||
], | ||
"keywords": [ | ||
"querystring", | ||
"qs" | ||
], | ||
"engines": { | ||
"node": ">=0.6" | ||
}, | ||
"devDependencies": { | ||
"@ljharb/eslint-config": "^20.1.0", | ||
"aud": "^1.1.5", | ||
"browserify": "^16.5.2", | ||
"eclint": "^2.8.1", | ||
"eslint": "^8.6.0", | ||
"evalmd": "^0.0.17", | ||
"iconv-lite": "^0.4.24", | ||
"in-publish": "^2.0.1", | ||
"mkdirp": "^0.5.1", | ||
"nyc": "^10.3.2", | ||
"qs-iconv": "^1.0.4", | ||
"safe-publish-latest": "^2.0.0", | ||
"safer-buffer": "^2.1.2", | ||
"tape": "^5.4.0" | ||
}, | ||
"scripts": { | ||
"prepublishOnly": "safe-publish-latest && npm run dist", | ||
"prepublish": "not-in-publish || npm run prepublishOnly", | ||
"pretest": "npm run --silent readme && npm run --silent lint", | ||
"test": "npm run --silent tests-only", | ||
"tests-only": "nyc tape 'test/**/*.js'", | ||
"posttest": "aud --production", | ||
"readme": "evalmd README.md", | ||
"postlint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git')", | ||
"lint": "eslint --ext=js,mjs .", | ||
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js" | ||
}, | ||
"license": "BSD-3-Clause" | ||
} |
@@ -172,3 +172,3 @@ # qs | ||
**qs** will also limit specifying indices in an array to a maximum index of `20`. Any array members with an index of greater than `20` will | ||
instead be converted to an object with the index as the key: | ||
instead be converted to an object with the index as the key. This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array. | ||
@@ -249,2 +249,26 @@ ```javascript | ||
You can encode keys and values using different logic by using the type argument provided to the encoder: | ||
```javascript | ||
var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultEncoder, charset, type) { | ||
if (type === 'key') { | ||
return // Encoded key | ||
} else if (type === 'value') { | ||
return // Encoded value | ||
} | ||
}}) | ||
``` | ||
The type argument is also provided to the decoder: | ||
```javascript | ||
var decoded = qs.parse('x=z', { decoder: function (str, defaultDecoder, charset, type) { | ||
if (type === 'key') { | ||
return // Decoded key | ||
} else if (type === 'value') { | ||
return // Decoded value | ||
} | ||
}}) | ||
``` | ||
Examples beyond this point will be shown as though the output is not URI encoded for clarity. Please note that the return values in these cases *will* be URI encoded during real usage. | ||
@@ -405,3 +429,3 @@ | ||
By default the encoding and decoding of characters is done in `utf-8`. If you | ||
By default the encoding and decoding of characters is done in `utf-8`. If you | ||
wish to encode querystrings to a different character set (i.e. | ||
@@ -408,0 +432,0 @@ [Shift JIS](https://en.wikipedia.org/wiki/Shift_JIS)) you can use the |
@@ -6,2 +6,3 @@ 'use strict'; | ||
var iconv = require('iconv-lite'); | ||
var SaferBuffer = require('safer-buffer').Buffer; | ||
@@ -234,3 +235,3 @@ test('parse()', function (t) { | ||
t.test('parses buffers correctly', function (st) { | ||
var b = new Buffer('test'); | ||
var b = SaferBuffer.from('test'); | ||
st.deepEqual(qs.parse({ a: b }), { a: b }); | ||
@@ -260,3 +261,3 @@ st.end(); | ||
t.test('should not throw when a native prototype has an enumerable property', { parallel: false }, function (st) { | ||
t.test('should not throw when a native prototype has an enumerable property', function (st) { | ||
Object.prototype.crash = ''; | ||
@@ -306,3 +307,10 @@ Array.prototype.crash = ''; | ||
t.test('allows disabling array parsing', function (st) { | ||
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { parseArrays: false }), { a: { 0: 'b', 1: 'c' } }); | ||
var indices = qs.parse('a[0]=b&a[1]=c', { parseArrays: false }); | ||
st.deepEqual(indices, { a: { 0: 'b', 1: 'c' } }); | ||
st.equal(Array.isArray(indices.a), false, 'parseArrays:false, indices case is not an array'); | ||
var emptyBrackets = qs.parse('a[]=b', { parseArrays: false }); | ||
st.deepEqual(emptyBrackets, { a: { 0: 'b' } }); | ||
st.equal(Array.isArray(emptyBrackets.a), false, 'parseArrays:false, empty brackets case is not an array'); | ||
st.end(); | ||
@@ -479,3 +487,3 @@ }); | ||
qs.parse('a[b]=c&a=toString', { plainObjects: true }), | ||
{ a: { b: 'c', toString: true } }, | ||
{ __proto__: null, a: { __proto__: null, b: 'c', toString: true } }, | ||
'can overwrite prototype with plainObjects true' | ||
@@ -487,2 +495,62 @@ ); | ||
t.test('dunder proto is ignored', function (st) { | ||
var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42'; | ||
var result = qs.parse(payload, { allowPrototypes: true }); | ||
st.deepEqual( | ||
result, | ||
{ | ||
categories: { | ||
length: '42' | ||
} | ||
}, | ||
'silent [[Prototype]] payload' | ||
); | ||
var plainResult = qs.parse(payload, { allowPrototypes: true, plainObjects: true }); | ||
st.deepEqual( | ||
plainResult, | ||
{ | ||
__proto__: null, | ||
categories: { | ||
__proto__: null, | ||
length: '42' | ||
} | ||
}, | ||
'silent [[Prototype]] payload: plain objects' | ||
); | ||
var query = qs.parse('categories[__proto__]=cats&categories[__proto__]=dogs&categories[some][json]=toInject', { allowPrototypes: true }); | ||
st.notOk(Array.isArray(query.categories), 'is not an array'); | ||
st.notOk(query.categories instanceof Array, 'is not instanceof an array'); | ||
st.deepEqual(query.categories, { some: { json: 'toInject' } }); | ||
st.equal(JSON.stringify(query.categories), '{"some":{"json":"toInject"}}', 'stringifies as a non-array'); | ||
st.deepEqual( | ||
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true }), | ||
{ | ||
foo: { | ||
bar: 'stuffs' | ||
} | ||
}, | ||
'hidden values' | ||
); | ||
st.deepEqual( | ||
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true, plainObjects: true }), | ||
{ | ||
__proto__: null, | ||
foo: { | ||
__proto__: null, | ||
bar: 'stuffs' | ||
} | ||
}, | ||
'hidden values: plain objects' | ||
); | ||
st.end(); | ||
}); | ||
t.test('can return null objects', { skip: !Object.create }, function (st) { | ||
@@ -513,3 +581,3 @@ var expected = Object.create(null); | ||
} | ||
return iconv.decode(new Buffer(result), 'shift_jis').toString(); | ||
return iconv.decode(SaferBuffer.from(result), 'shift_jis').toString(); | ||
} | ||
@@ -521,3 +589,3 @@ }), { 県: '大阪府' }); | ||
t.test('throws error with wrong decoder', function (st) { | ||
st.throws(function () { | ||
st['throws'](function () { | ||
qs.parse({}, { decoder: 'string' }); | ||
@@ -524,0 +592,0 @@ }, new TypeError('Decoder has to be a function.')); |
@@ -6,2 +6,3 @@ 'use strict'; | ||
var iconv = require('iconv-lite'); | ||
var SaferBuffer = require('safer-buffer').Buffer; | ||
@@ -329,4 +330,4 @@ test('stringify()', function (t) { | ||
t.test('stringifies buffer values', function (st) { | ||
st.equal(qs.stringify({ a: new Buffer('test') }), 'a=test'); | ||
st.equal(qs.stringify({ a: { b: new Buffer('test') } }), 'a%5Bb%5D=test'); | ||
st.equal(qs.stringify({ a: SaferBuffer.from('test') }), 'a=test'); | ||
st.equal(qs.stringify({ a: { b: SaferBuffer.from('test') } }), 'a%5Bb%5D=test'); | ||
st.end(); | ||
@@ -458,3 +459,3 @@ }); | ||
t.test('throws error with wrong encoder', function (st) { | ||
st.throws(function () { | ||
st['throws'](function () { | ||
qs.stringify({}, { encoder: 'string' }); | ||
@@ -466,3 +467,3 @@ }, new TypeError('Encoder has to be a function.')); | ||
t.test('can use custom encoder for a buffer object', { skip: typeof Buffer === 'undefined' }, function (st) { | ||
st.equal(qs.stringify({ a: new Buffer([1]) }, { | ||
st.equal(qs.stringify({ a: SaferBuffer.from([1]) }, { | ||
encoder: function (buffer) { | ||
@@ -475,2 +476,8 @@ if (typeof buffer === 'string') { | ||
}), 'a=b'); | ||
st.equal(qs.stringify({ a: SaferBuffer.from('a b') }, { | ||
encoder: function (buffer) { | ||
return buffer; | ||
} | ||
}), 'a=a b'); | ||
st.end(); | ||
@@ -491,3 +498,3 @@ }); | ||
}; | ||
st.throws(function () { | ||
st['throws'](function () { | ||
mutatedDate.toISOString(); | ||
@@ -517,2 +524,3 @@ }, SyntaxError); | ||
st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC1738 }), 'a+b=c+d'); | ||
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC1738 }), 'a+b=a+b'); | ||
st.end(); | ||
@@ -524,2 +532,3 @@ }); | ||
st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC3986 }), 'a%20b=c%20d'); | ||
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC3986 }), 'a%20b=a%20b'); | ||
st.end(); | ||
@@ -530,2 +539,3 @@ }); | ||
st.equal(qs.stringify({ a: 'b c' }), 'a=b%20c'); | ||
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }), 'a%20b=a%20b'); | ||
st.end(); | ||
@@ -535,14 +545,34 @@ }); | ||
t.test('Edge cases and unknown formats', function (st) { | ||
['UFO1234', false, 1234, null, {}, []].forEach( | ||
function (format) { | ||
st.throws( | ||
function () { | ||
qs.stringify({ a: 'b c' }, { format: format }); | ||
}, | ||
new TypeError('Unknown format option provided.') | ||
); | ||
} | ||
); | ||
['UFO1234', false, 1234, null, {}, []].forEach(function (format) { | ||
st['throws']( | ||
function () { | ||
qs.stringify({ a: 'b c' }, { format: format }); | ||
}, | ||
new TypeError('Unknown format option provided.') | ||
); | ||
}); | ||
st.end(); | ||
}); | ||
t.test('strictNullHandling works with custom filter', function (st) { | ||
var filter = function (prefix, value) { | ||
return value; | ||
}; | ||
var options = { strictNullHandling: true, filter: filter }; | ||
st.equal(qs.stringify({ key: null }, options), 'key'); | ||
st.end(); | ||
}); | ||
t.test('strictNullHandling works with null serializeDate', function (st) { | ||
var serializeDate = function () { | ||
return null; | ||
}; | ||
var options = { strictNullHandling: true, serializeDate: serializeDate }; | ||
var date = new Date(); | ||
st.equal(qs.stringify({ key: date }, options), 'key'); | ||
st.end(); | ||
}); | ||
t.end(); | ||
}); |
@@ -7,2 +7,6 @@ 'use strict'; | ||
test('merge()', function (t) { | ||
t.deepEqual(utils.merge(null, true), [null, true], 'merges true into null'); | ||
t.deepEqual(utils.merge(null, [42]), [null, 42], 'merges null into an array'); | ||
t.deepEqual(utils.merge({ a: 'b' }, { a: 'c' }), { a: ['b', 'c'] }, 'merges two objects with the same key'); | ||
@@ -22,3 +26,6 @@ | ||
var noOptionsNonObjectSource = utils.merge({ foo: 'baz' }, 'bar'); | ||
t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true }); | ||
t.end(); | ||
}); |
Sorry, the diff of this file is not supported yet
111131
20
2041
456
14