44
55const  QueryString  =  exports ; 
66
7- // If obj.hasOwnProperty has been overridden, then calling 
8- // obj.hasOwnProperty(prop) will break. 
9- // See: https://github.com/joyent/node/issues/1707 
10- function  hasOwnProperty ( obj ,  prop )  { 
11-   return  Object . prototype . hasOwnProperty . call ( obj ,  prop ) ; 
12- } 
13- 
147
158function  charCode ( c )  { 
169  return  c . charCodeAt ( 0 ) ; 
@@ -93,19 +86,68 @@ QueryString.unescape = function(s, decodeSpaces) {
9386} ; 
9487
9588
89+ var  hexTable  =  new  Array ( 256 ) ; 
90+ for  ( var  i  =  0 ;  i  <  256 ;  ++ i ) 
91+   hexTable [ i ]  =  '%'  +  ( ( i  <  16  ? '0'  : '' )  +  i . toString ( 16 ) ) . toUpperCase ( ) ; 
9692QueryString . escape  =  function ( str )  { 
97-   return  encodeURIComponent ( str ) ; 
93+   var  len  =  str . length ; 
94+   var  out  =  '' ; 
95+   var  i ,  c ; 
96+ 
97+   if  ( len  ===  0 ) 
98+     return  str ; 
99+ 
100+   for  ( i  =  0 ;  i  <  len ;  ++ i )  { 
101+     c  =  str . charCodeAt ( i ) ; 
102+ 
103+     // These characters do not need escaping (in order): 
104+     // ! - . _ ~ 
105+     // ' ( ) * 
106+     // digits 
107+     // alpha (uppercase) 
108+     // alpha (lowercase) 
109+     if  ( c  ===  0x21  ||  c  ===  0x2D  ||  c  ===  0x2E  ||  c  ===  0x5F  ||  c  ===  0x7E  || 
110+         ( c  >=  0x27  &&  c  <=  0x2A )  || 
111+         ( c  >=  0x30  &&  c  <=  0x39 )  || 
112+         ( c  >=  0x41  &&  c  <=  0x5A )  || 
113+         ( c  >=  0x61  &&  c  <=  0x7A ) )  { 
114+       out  +=  str [ i ] ; 
115+       continue ; 
116+     } 
117+ 
118+     // Other ASCII characters 
119+     if  ( c  <  0x80 )  { 
120+       out  +=  hexTable [ c ] ; 
121+       continue ; 
122+     } 
123+ 
124+     // Multi-byte characters ... 
125+     if  ( c  <  0x800 )  { 
126+       out  +=  hexTable [ 0xC0  |  ( c  >>  6 ) ]  +  hexTable [ 0x80  |  ( c  &  0x3F ) ] ; 
127+       continue ; 
128+     } 
129+     if  ( c  <  0xD800  ||  c  >=  0xE000 )  { 
130+       out  +=  hexTable [ 0xE0  |  ( c  >>  12 ) ]  + 
131+              hexTable [ 0x80  |  ( ( c  >>  6 )  &  0x3F ) ]  + 
132+              hexTable [ 0x80  |  ( c  &  0x3F ) ] ; 
133+       continue ; 
134+     } 
135+     // Surrogate pair 
136+     ++ i ; 
137+     c  =  0x10000  +  ( ( ( c  &  0x3FF )  <<  10 )  |  ( str . charCodeAt ( i )  &  0x3FF ) ) ; 
138+     out  +=  hexTable [ 0xF0  |  ( c  >>  18 ) ]  + 
139+            hexTable [ 0x80  |  ( ( c  >>  12 )  &  0x3F ) ]  + 
140+            hexTable [ 0x80  |  ( ( c  >>  6 )  &  0x3F ) ]  + 
141+            hexTable [ 0x80  |  ( c  &  0x3F ) ] ; 
142+   } 
143+   return  out ; 
98144} ; 
99145
100146var  stringifyPrimitive  =  function ( v )  { 
101-   let  type  =  typeof  v ; 
102- 
103-   if  ( type  ===  'string' ) 
147+   if  ( typeof  v  ===  'string'  ||  ( typeof  v  ===  'number'  &&  isFinite ( v ) ) ) 
104148    return  v ; 
105-   if  ( type  ===  'boolean' ) 
149+   if  ( typeof   v  ===  'boolean' ) 
106150    return  v  ? 'true'  : 'false' ; 
107-   if  ( type  ===  'number' ) 
108-     return  isFinite ( v )  ? v  : '' ; 
109151  return  '' ; 
110152} ; 
111153
@@ -121,21 +163,31 @@ QueryString.stringify = QueryString.encode = function(obj, sep, eq, options) {
121163
122164  if  ( obj  !==  null  &&  typeof  obj  ===  'object' )  { 
123165    var  keys  =  Object . keys ( obj ) ; 
124-     var  fields  =  [ ] ; 
125- 
126-     for  ( var  i  =  0 ;  i  <  keys . length ;  i ++ )  { 
166+     var  len  =  keys . length ; 
167+     var  flast  =  len  -  1 ; 
168+     var  fields  =  '' ; 
169+     for  ( var  i  =  0 ;  i  <  len ;  ++ i )  { 
127170      var  k  =  keys [ i ] ; 
128171      var  v  =  obj [ k ] ; 
129172      var  ks  =  encode ( stringifyPrimitive ( k ) )  +  eq ; 
130173
131174      if  ( Array . isArray ( v ) )  { 
132-         for  ( var  j  =  0 ;  j  <  v . length ;  j ++ ) 
133-           fields . push ( ks  +  encode ( stringifyPrimitive ( v [ j ] ) ) ) ; 
175+         var  vlen  =  v . length ; 
176+         var  vlast  =  vlen  -  1 ; 
177+         for  ( var  j  =  0 ;  j  <  vlen ;  ++ j )  { 
178+           fields  +=  ks  +  encode ( stringifyPrimitive ( v [ j ] ) ) ; 
179+           if  ( j  <  vlast ) 
180+             fields  +=  sep ; 
181+         } 
182+         if  ( vlen  &&  i  <  flast ) 
183+           fields  +=  sep ; 
134184      }  else  { 
135-         fields . push ( ks  +  encode ( stringifyPrimitive ( v ) ) ) ; 
185+         fields  +=  ks  +  encode ( stringifyPrimitive ( v ) ) ; 
186+         if  ( i  <  flast ) 
187+           fields  +=  sep ; 
136188      } 
137189    } 
138-     return  fields . join ( sep ) ; 
190+     return  fields ; 
139191  } 
140192  return  '' ; 
141193} ; 
@@ -169,29 +221,23 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
169221    decode  =  options . decodeURIComponent ; 
170222  } 
171223
224+   var  keys  =  [ ] ; 
172225  for  ( var  i  =  0 ;  i  <  len ;  ++ i )  { 
173226    var  x  =  qs [ i ] . replace ( regexp ,  '%20' ) , 
174227        idx  =  x . indexOf ( eq ) , 
175-         kstr ,   vstr ,   k ,  v ; 
228+         k ,  v ; 
176229
177230    if  ( idx  >=  0 )  { 
178-       kstr  =  x . substr ( 0 ,  idx ) ; 
179-       vstr  =  x . substr ( idx  +  1 ) ; 
231+       k  =  decodeStr ( x . substring ( 0 ,  idx ) ,   decode ) ; 
232+       v  =  decodeStr ( x . substring ( idx  +  1 ) ,   decode ) ; 
180233    }  else  { 
181-       kstr  =  x ; 
182-       vstr  =  '' ; 
234+       k  =  decodeStr ( x ,   decode ) ; 
235+       v  =  '' ; 
183236    } 
184237
185-     try  { 
186-       k  =  decode ( kstr ) ; 
187-       v  =  decode ( vstr ) ; 
188-     }  catch  ( e )  { 
189-       k  =  QueryString . unescape ( kstr ,  true ) ; 
190-       v  =  QueryString . unescape ( vstr ,  true ) ; 
191-     } 
192- 
193-     if  ( ! hasOwnProperty ( obj ,  k ) )  { 
238+     if  ( keys . indexOf ( k )  ===  - 1 )  { 
194239      obj [ k ]  =  v ; 
240+       keys . push ( k ) ; 
195241    }  else  if  ( Array . isArray ( obj [ k ] ) )  { 
196242      obj [ k ] . push ( v ) ; 
197243    }  else  { 
@@ -201,3 +247,12 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
201247
202248  return  obj ; 
203249} ; 
250+ 
251+ 
252+ function  decodeStr ( s ,  decoder )  { 
253+   try  { 
254+     return  decoder ( s ) ; 
255+   }  catch  ( e )  { 
256+     return  QueryString . unescape ( s ,  true ) ; 
257+   } 
258+ } 
0 commit comments