1'use strict'; 2 3var has = Object.prototype.hasOwnProperty; 4 5var hexTable = (function () { 6 var array = []; 7 for (var i = 0; i < 256; ++i) { 8 array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase()); 9 } 10 11 return array; 12}()); 13 14var compactQueue = function compactQueue(queue) { 15 var obj; 16 17 while (queue.length) { 18 var item = queue.pop(); 19 obj = item.obj[item.prop]; 20 21 if (Array.isArray(obj)) { 22 var compacted = []; 23 24 for (var j = 0; j < obj.length; ++j) { 25 if (typeof obj[j] !== 'undefined') { 26 compacted.push(obj[j]); 27 } 28 } 29 30 item.obj[item.prop] = compacted; 31 } 32 } 33 34 return obj; 35}; 36 37var arrayToObject = function arrayToObject(source, options) { 38 var obj = options && options.plainObjects ? Object.create(null) : {}; 39 for (var i = 0; i < source.length; ++i) { 40 if (typeof source[i] !== 'undefined') { 41 obj[i] = source[i]; 42 } 43 } 44 45 return obj; 46}; 47 48var merge = function merge(target, source, options) { 49 if (!source) { 50 return target; 51 } 52 53 if (typeof source !== 'object') { 54 if (Array.isArray(target)) { 55 target.push(source); 56 } else if (typeof target === 'object') { 57 if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) { 58 target[source] = true; 59 } 60 } else { 61 return [target, source]; 62 } 63 64 return target; 65 } 66 67 if (typeof target !== 'object') { 68 return [target].concat(source); 69 } 70 71 var mergeTarget = target; 72 if (Array.isArray(target) && !Array.isArray(source)) { 73 mergeTarget = arrayToObject(target, options); 74 } 75 76 if (Array.isArray(target) && Array.isArray(source)) { 77 source.forEach(function (item, i) { 78 if (has.call(target, i)) { 79 if (target[i] && typeof target[i] === 'object') { 80 target[i] = merge(target[i], item, options); 81 } else { 82 target.push(item); 83 } 84 } else { 85 target[i] = item; 86 } 87 }); 88 return target; 89 } 90 91 return Object.keys(source).reduce(function (acc, key) { 92 var value = source[key]; 93 94 if (has.call(acc, key)) { 95 acc[key] = merge(acc[key], value, options); 96 } else { 97 acc[key] = value; 98 } 99 return acc; 100 }, mergeTarget); 101}; 102 103var assign = function assignSingleSource(target, source) { 104 return Object.keys(source).reduce(function (acc, key) { 105 acc[key] = source[key]; 106 return acc; 107 }, target); 108}; 109 110var decode = function (str) { 111 try { 112 return decodeURIComponent(str.replace(/\+/g, ' ')); 113 } catch (e) { 114 return str; 115 } 116}; 117 118var encode = function encode(str) { 119 // This code was originally written by Brian White (mscdex) for the io.js core querystring library. 120 // It has been adapted here for stricter adherence to RFC 3986 121 if (str.length === 0) { 122 return str; 123 } 124 125 var string = typeof str === 'string' ? str : String(str); 126 127 var out = ''; 128 for (var i = 0; i < string.length; ++i) { 129 var c = string.charCodeAt(i); 130 131 if ( 132 c === 0x2D // - 133 || c === 0x2E // . 134 || c === 0x5F // _ 135 || c === 0x7E // ~ 136 || (c >= 0x30 && c <= 0x39) // 0-9 137 || (c >= 0x41 && c <= 0x5A) // a-z 138 || (c >= 0x61 && c <= 0x7A) // A-Z 139 ) { 140 out += string.charAt(i); 141 continue; 142 } 143 144 if (c < 0x80) { 145 out = out + hexTable[c]; 146 continue; 147 } 148 149 if (c < 0x800) { 150 out = out + (hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]); 151 continue; 152 } 153 154 if (c < 0xD800 || c >= 0xE000) { 155 out = out + (hexTable[0xE0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]); 156 continue; 157 } 158 159 i += 1; 160 c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF)); 161 out += hexTable[0xF0 | (c >> 18)] 162 + hexTable[0x80 | ((c >> 12) & 0x3F)] 163 + hexTable[0x80 | ((c >> 6) & 0x3F)] 164 + hexTable[0x80 | (c & 0x3F)]; 165 } 166 167 return out; 168}; 169 170var compact = function compact(value) { 171 var queue = [{ obj: { o: value }, prop: 'o' }]; 172 var refs = []; 173 174 for (var i = 0; i < queue.length; ++i) { 175 var item = queue[i]; 176 var obj = item.obj[item.prop]; 177 178 var keys = Object.keys(obj); 179 for (var j = 0; j < keys.length; ++j) { 180 var key = keys[j]; 181 var val = obj[key]; 182 if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) { 183 queue.push({ obj: obj, prop: key }); 184 refs.push(val); 185 } 186 } 187 } 188 189 return compactQueue(queue); 190}; 191 192var isRegExp = function isRegExp(obj) { 193 return Object.prototype.toString.call(obj) === '[object RegExp]'; 194}; 195 196var isBuffer = function isBuffer(obj) { 197 if (obj === null || typeof obj === 'undefined') { 198 return false; 199 } 200 201 return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj)); 202}; 203 204module.exports = { 205 arrayToObject: arrayToObject, 206 assign: assign, 207 compact: compact, 208 decode: decode, 209 encode: encode, 210 isBuffer: isBuffer, 211 isRegExp: isRegExp, 212 merge: merge 213}; 214