/ node_modules / qs / lib / utils.js
utils.js
  1  'use strict';
  2  
  3  var formats = require('./formats');
  4  
  5  var has = Object.prototype.hasOwnProperty;
  6  var isArray = Array.isArray;
  7  
  8  var hexTable = (function () {
  9      var array = [];
 10      for (var i = 0; i < 256; ++i) {
 11          array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
 12      }
 13  
 14      return array;
 15  }());
 16  
 17  var compactQueue = function compactQueue(queue) {
 18      while (queue.length > 1) {
 19          var item = queue.pop();
 20          var obj = item.obj[item.prop];
 21  
 22          if (isArray(obj)) {
 23              var compacted = [];
 24  
 25              for (var j = 0; j < obj.length; ++j) {
 26                  if (typeof obj[j] !== 'undefined') {
 27                      compacted.push(obj[j]);
 28                  }
 29              }
 30  
 31              item.obj[item.prop] = compacted;
 32          }
 33      }
 34  };
 35  
 36  var arrayToObject = function arrayToObject(source, options) {
 37      var obj = options && options.plainObjects ? { __proto__: null } : {};
 38      for (var i = 0; i < source.length; ++i) {
 39          if (typeof source[i] !== 'undefined') {
 40              obj[i] = source[i];
 41          }
 42      }
 43  
 44      return obj;
 45  };
 46  
 47  var merge = function merge(target, source, options) {
 48      /* eslint no-param-reassign: 0 */
 49      if (!source) {
 50          return target;
 51      }
 52  
 53      if (typeof source !== 'object' && typeof source !== 'function') {
 54          if (isArray(target)) {
 55              target.push(source);
 56          } else if (target && typeof target === 'object') {
 57              if (
 58                  (options && (options.plainObjects || options.allowPrototypes))
 59                  || !has.call(Object.prototype, source)
 60              ) {
 61                  target[source] = true;
 62              }
 63          } else {
 64              return [target, source];
 65          }
 66  
 67          return target;
 68      }
 69  
 70      if (!target || typeof target !== 'object') {
 71          return [target].concat(source);
 72      }
 73  
 74      var mergeTarget = target;
 75      if (isArray(target) && !isArray(source)) {
 76          mergeTarget = arrayToObject(target, options);
 77      }
 78  
 79      if (isArray(target) && isArray(source)) {
 80          source.forEach(function (item, i) {
 81              if (has.call(target, i)) {
 82                  var targetItem = target[i];
 83                  if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
 84                      target[i] = merge(targetItem, item, options);
 85                  } else {
 86                      target.push(item);
 87                  }
 88              } else {
 89                  target[i] = item;
 90              }
 91          });
 92          return target;
 93      }
 94  
 95      return Object.keys(source).reduce(function (acc, key) {
 96          var value = source[key];
 97  
 98          if (has.call(acc, key)) {
 99              acc[key] = merge(acc[key], value, options);
100          } else {
101              acc[key] = value;
102          }
103          return acc;
104      }, mergeTarget);
105  };
106  
107  var assign = function assignSingleSource(target, source) {
108      return Object.keys(source).reduce(function (acc, key) {
109          acc[key] = source[key];
110          return acc;
111      }, target);
112  };
113  
114  var decode = function (str, defaultDecoder, charset) {
115      var strWithoutPlus = str.replace(/\+/g, ' ');
116      if (charset === 'iso-8859-1') {
117          // unescape never throws, no try...catch needed:
118          return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape);
119      }
120      // utf-8
121      try {
122          return decodeURIComponent(strWithoutPlus);
123      } catch (e) {
124          return strWithoutPlus;
125      }
126  };
127  
128  var limit = 1024;
129  
130  /* eslint operator-linebreak: [2, "before"] */
131  
132  var encode = function encode(str, defaultEncoder, charset, kind, format) {
133      // This code was originally written by Brian White (mscdex) for the io.js core querystring library.
134      // It has been adapted here for stricter adherence to RFC 3986
135      if (str.length === 0) {
136          return str;
137      }
138  
139      var string = str;
140      if (typeof str === 'symbol') {
141          string = Symbol.prototype.toString.call(str);
142      } else if (typeof str !== 'string') {
143          string = String(str);
144      }
145  
146      if (charset === 'iso-8859-1') {
147          return escape(string).replace(/%u[0-9a-f]{4}/gi, function ($0) {
148              return '%26%23' + parseInt($0.slice(2), 16) + '%3B';
149          });
150      }
151  
152      var out = '';
153      for (var j = 0; j < string.length; j += limit) {
154          var segment = string.length >= limit ? string.slice(j, j + limit) : string;
155          var arr = [];
156  
157          for (var i = 0; i < segment.length; ++i) {
158              var c = segment.charCodeAt(i);
159              if (
160                  c === 0x2D // -
161                  || c === 0x2E // .
162                  || c === 0x5F // _
163                  || c === 0x7E // ~
164                  || (c >= 0x30 && c <= 0x39) // 0-9
165                  || (c >= 0x41 && c <= 0x5A) // a-z
166                  || (c >= 0x61 && c <= 0x7A) // A-Z
167                  || (format === formats.RFC1738 && (c === 0x28 || c === 0x29)) // ( )
168              ) {
169                  arr[arr.length] = segment.charAt(i);
170                  continue;
171              }
172  
173              if (c < 0x80) {
174                  arr[arr.length] = hexTable[c];
175                  continue;
176              }
177  
178              if (c < 0x800) {
179                  arr[arr.length] = hexTable[0xC0 | (c >> 6)]
180                      + hexTable[0x80 | (c & 0x3F)];
181                  continue;
182              }
183  
184              if (c < 0xD800 || c >= 0xE000) {
185                  arr[arr.length] = hexTable[0xE0 | (c >> 12)]
186                      + hexTable[0x80 | ((c >> 6) & 0x3F)]
187                      + hexTable[0x80 | (c & 0x3F)];
188                  continue;
189              }
190  
191              i += 1;
192              c = 0x10000 + (((c & 0x3FF) << 10) | (segment.charCodeAt(i) & 0x3FF));
193  
194              arr[arr.length] = hexTable[0xF0 | (c >> 18)]
195                  + hexTable[0x80 | ((c >> 12) & 0x3F)]
196                  + hexTable[0x80 | ((c >> 6) & 0x3F)]
197                  + hexTable[0x80 | (c & 0x3F)];
198          }
199  
200          out += arr.join('');
201      }
202  
203      return out;
204  };
205  
206  var compact = function compact(value) {
207      var queue = [{ obj: { o: value }, prop: 'o' }];
208      var refs = [];
209  
210      for (var i = 0; i < queue.length; ++i) {
211          var item = queue[i];
212          var obj = item.obj[item.prop];
213  
214          var keys = Object.keys(obj);
215          for (var j = 0; j < keys.length; ++j) {
216              var key = keys[j];
217              var val = obj[key];
218              if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
219                  queue.push({ obj: obj, prop: key });
220                  refs.push(val);
221              }
222          }
223      }
224  
225      compactQueue(queue);
226  
227      return value;
228  };
229  
230  var isRegExp = function isRegExp(obj) {
231      return Object.prototype.toString.call(obj) === '[object RegExp]';
232  };
233  
234  var isBuffer = function isBuffer(obj) {
235      if (!obj || typeof obj !== 'object') {
236          return false;
237      }
238  
239      return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
240  };
241  
242  var combine = function combine(a, b) {
243      return [].concat(a, b);
244  };
245  
246  var maybeMap = function maybeMap(val, fn) {
247      if (isArray(val)) {
248          var mapped = [];
249          for (var i = 0; i < val.length; i += 1) {
250              mapped.push(fn(val[i]));
251          }
252          return mapped;
253      }
254      return fn(val);
255  };
256  
257  module.exports = {
258      arrayToObject: arrayToObject,
259      assign: assign,
260      combine: combine,
261      compact: compact,
262      decode: decode,
263      encode: encode,
264      isBuffer: isBuffer,
265      isRegExp: isRegExp,
266      maybeMap: maybeMap,
267      merge: merge
268  };