@ -4,13 +4,6 @@
const QueryString = exports ;
// If obj.hasOwnProperty has been overridden, then calling
// obj.hasOwnProperty(prop) will break.
// See: https://github.com/joyent/node/issues/1707
function hasOwnProperty ( obj , prop ) {
return Object . prototype . hasOwnProperty . call ( obj , prop ) ;
}
function charCode ( c ) {
return c . charCodeAt ( 0 ) ;
@ -93,19 +86,68 @@ QueryString.unescape = function(s, decodeSpaces) {
} ;
var hexTable = new Array ( 256 ) ;
for ( var i = 0 ; i < 256 ; ++ i )
hexTable [ i ] = '%' + ( ( i < 16 ? '0' : '' ) + i . toString ( 16 ) ) . toUpperCase ( ) ;
QueryString . escape = function ( str ) {
return encodeURIComponent ( str ) ;
var len = str . length ;
var out = '' ;
var i , c ;
if ( len === 0 )
return str ;
for ( i = 0 ; i < len ; ++ i ) {
c = str . charCodeAt ( i ) ;
// These characters do not need escaping (in order):
// ! - . _ ~
// ' ( ) *
// digits
// alpha (uppercase)
// alpha (lowercase)
if ( c === 0x21 || c === 0x2D || c === 0x2E || c === 0x5F || c === 0x7E ||
( c >= 0x27 && c <= 0x2A ) ||
( c >= 0x30 && c <= 0x39 ) ||
( c >= 0x41 && c <= 0x5A ) ||
( c >= 0x61 && c <= 0x7A ) ) {
out += str [ i ] ;
continue ;
}
// Other ASCII characters
if ( c < 0x80 ) {
out += hexTable [ c ] ;
continue ;
}
// Multi-byte characters ...
if ( c < 0x800 ) {
out += hexTable [ 0xC0 | ( c >> 6 ) ] + hexTable [ 0x80 | ( c & 0x3F ) ] ;
continue ;
}
if ( c < 0xD800 || c >= 0xE000 ) {
out += hexTable [ 0xE0 | ( c >> 12 ) ] +
hexTable [ 0x80 | ( ( c >> 6 ) & 0x3F ) ] +
hexTable [ 0x80 | ( c & 0x3F ) ] ;
continue ;
}
// Surrogate pair
++ i ;
c = 0x10000 + ( ( ( c & 0x3FF ) << 10 ) | ( str . charCodeAt ( i ) & 0x3FF ) ) ;
out += hexTable [ 0xF0 | ( c >> 18 ) ] +
hexTable [ 0x80 | ( ( c >> 12 ) & 0x3F ) ] +
hexTable [ 0x80 | ( ( c >> 6 ) & 0x3F ) ] +
hexTable [ 0x80 | ( c & 0x3F ) ] ;
}
return out ;
} ;
var stringifyPrimitive = function ( v ) {
let type = typeof v ;
if ( type === 'string' )
if ( typeof v === 'string' || ( typeof v === 'number' && isFinite ( v ) ) )
return v ;
if ( type === 'boolean' )
if ( typeof v === 'boolean' )
return v ? 'true' : 'false' ;
if ( type === 'number' )
return isFinite ( v ) ? v : '' ;
return '' ;
} ;
@ -121,21 +163,31 @@ QueryString.stringify = QueryString.encode = function(obj, sep, eq, options) {
if ( obj !== null && typeof obj === 'object' ) {
var keys = Object . keys ( obj ) ;
var fields = [ ] ;
for ( var i = 0 ; i < keys . length ; i ++ ) {
var len = keys . length ;
var flast = len - 1 ;
var fields = '' ;
for ( var i = 0 ; i < len ; ++ i ) {
var k = keys [ i ] ;
var v = obj [ k ] ;
var ks = encode ( stringifyPrimitive ( k ) ) + eq ;
if ( Array . isArray ( v ) ) {
for ( var j = 0 ; j < v . length ; j ++ )
fields . push ( ks + encode ( stringifyPrimitive ( v [ j ] ) ) ) ;
var vlen = v . length ;
var vlast = vlen - 1 ;
for ( var j = 0 ; j < vlen ; ++ j ) {
fields += ks + encode ( stringifyPrimitive ( v [ j ] ) ) ;
if ( j < vlast )
fields += sep ;
}
if ( vlen && i < flast )
fields += sep ;
} else {
fields . push ( ks + encode ( stringifyPrimitive ( v ) ) ) ;
fields += ks + encode ( stringifyPrimitive ( v ) ) ;
if ( i < flast )
fields += sep ;
}
}
return fields . join ( sep ) ;
return fields ;
}
return '' ;
} ;
@ -169,29 +221,23 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
decode = options . decodeURIComponent ;
}
var keys = [ ] ;
for ( var i = 0 ; i < len ; ++ i ) {
var x = qs [ i ] . replace ( regexp , '%20' ) ,
idx = x . indexOf ( eq ) ,
kstr , vstr , k , v ;
k , v ;
if ( idx >= 0 ) {
kstr = x . substr ( 0 , idx ) ;
vstr = x . substr ( idx + 1 ) ;
k = decodeStr ( x . substring ( 0 , idx ) , decode ) ;
v = decodeStr ( x . substring ( idx + 1 ) , decode ) ;
} else {
kstr = x ;
vstr = '' ;
k = decodeStr ( x , decode ) ;
v = '' ;
}
try {
k = decode ( kstr ) ;
v = decode ( vstr ) ;
} catch ( e ) {
k = QueryString . unescape ( kstr , true ) ;
v = QueryString . unescape ( vstr , true ) ;
}
if ( ! hasOwnProperty ( obj , k ) ) {
if ( keys . indexOf ( k ) === - 1 ) {
obj [ k ] = v ;
keys . push ( k ) ;
} else if ( Array . isArray ( obj [ k ] ) ) {
obj [ k ] . push ( v ) ;
} else {
@ -201,3 +247,12 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
return obj ;
} ;
function decodeStr ( s , decoder ) {
try {
return decoder ( s ) ;
} catch ( e ) {
return QueryString . unescape ( s , true ) ;
}
}