1/** 2 * 3 * 4 * @author Jerry Bendy <[email protected]> 5 * @licence MIT 6 * 7 */ 8 9(function(self) { 10 'use strict'; 11 12 var nativeURLSearchParams = (self.URLSearchParams && self.URLSearchParams.prototype.get) ? self.URLSearchParams : null, 13 isSupportObjectConstructor = nativeURLSearchParams && (new nativeURLSearchParams({a: 1})).toString() === 'a=1', 14 // There is a bug in safari 10.1 (and earlier) that incorrectly decodes `%2B` as an empty space and not a plus. 15 decodesPlusesCorrectly = nativeURLSearchParams && (new nativeURLSearchParams('s=%2B').get('s') === '+'), 16 __URLSearchParams__ = "__URLSearchParams__", 17 // Fix bug in Edge which cannot encode ' &' correctly 18 encodesAmpersandsCorrectly = nativeURLSearchParams ? (function() { 19 var ampersandTest = new nativeURLSearchParams(); 20 ampersandTest.append('s', ' &'); 21 return ampersandTest.toString() === 's=+%26'; 22 })() : true, 23 prototype = URLSearchParamsPolyfill.prototype, 24 iterable = !!(self.Symbol && self.Symbol.iterator); 25 26 if (nativeURLSearchParams && isSupportObjectConstructor && decodesPlusesCorrectly && encodesAmpersandsCorrectly) { 27 return; 28 } 29 30 31 /** 32 * Make a URLSearchParams instance 33 * 34 * @param {object|string|URLSearchParams} search 35 * @constructor 36 */ 37 function URLSearchParamsPolyfill(search) { 38 search = search || ""; 39 40 // support construct object with another URLSearchParams instance 41 if (search instanceof URLSearchParams || search instanceof URLSearchParamsPolyfill) { 42 search = search.toString(); 43 } 44 this [__URLSearchParams__] = parseToDict(search); 45 } 46 47 48 /** 49 * Appends a specified key/value pair as a new search parameter. 50 * 51 * @param {string} name 52 * @param {string} value 53 */ 54 prototype.append = function(name, value) { 55 appendTo(this [__URLSearchParams__], name, value); 56 }; 57 58 /** 59 * Deletes the given search parameter, and its associated value, 60 * from the list of all search parameters. 61 * 62 * @param {string} name 63 */ 64 prototype['delete'] = function(name) { 65 delete this [__URLSearchParams__] [name]; 66 }; 67 68 /** 69 * Returns the first value associated to the given search parameter. 70 * 71 * @param {string} name 72 * @returns {string|null} 73 */ 74 prototype.get = function(name) { 75 var dict = this [__URLSearchParams__]; 76 return this.has(name) ? dict[name][0] : null; 77 }; 78 79 /** 80 * Returns all the values association with a given search parameter. 81 * 82 * @param {string} name 83 * @returns {Array} 84 */ 85 prototype.getAll = function(name) { 86 var dict = this [__URLSearchParams__]; 87 return this.has(name) ? dict [name].slice(0) : []; 88 }; 89 90 /** 91 * Returns a Boolean indicating if such a search parameter exists. 92 * 93 * @param {string} name 94 * @returns {boolean} 95 */ 96 prototype.has = function(name) { 97 return hasOwnProperty(this [__URLSearchParams__], name); 98 }; 99 100 /** 101 * Sets the value associated to a given search parameter to 102 * the given value. If there were several values, delete the 103 * others. 104 * 105 * @param {string} name 106 * @param {string} value 107 */ 108 prototype.set = function set(name, value) { 109 this [__URLSearchParams__][name] = ['' + value]; 110 }; 111 112 /** 113 * Returns a string containg a query string suitable for use in a URL. 114 * 115 * @returns {string} 116 */ 117 prototype.toString = function() { 118 var dict = this[__URLSearchParams__], query = [], i, key, name, value; 119 for (key in dict) { 120 name = encode(key); 121 for (i = 0, value = dict[key]; i < value.length; i++) { 122 query.push(name + '=' + encode(value[i])); 123 } 124 } 125 return query.join('&'); 126 }; 127 128 // There is a bug in Safari 10.1 and `Proxy`ing it is not enough. 129 var forSureUsePolyfill = !decodesPlusesCorrectly; 130 var useProxy = (!forSureUsePolyfill && nativeURLSearchParams && !isSupportObjectConstructor && self.Proxy); 131 /* 132 * Apply polifill to global object and append other prototype into it 133 */ 134 Object.defineProperty(self, 'URLSearchParams', { 135 value: (useProxy ? 136 // Safari 10.0 doesn't support Proxy, so it won't extend URLSearchParams on safari 10.0 137 new Proxy(nativeURLSearchParams, { 138 construct: function(target, args) { 139 return new target((new URLSearchParamsPolyfill(args[0]).toString())); 140 } 141 }) : 142 URLSearchParamsPolyfill) 143 }); 144 145 var USPProto = self.URLSearchParams.prototype; 146 147 USPProto.polyfill = true; 148 149 /** 150 * 151 * @param {function} callback 152 * @param {object} thisArg 153 */ 154 USPProto.forEach = USPProto.forEach || function(callback, thisArg) { 155 var dict = parseToDict(this.toString()); 156 Object.getOwnPropertyNames(dict).forEach(function(name) { 157 dict[name].forEach(function(value) { 158 callback.call(thisArg, value, name, this); 159 }, this); 160 }, this); 161 }; 162 163 /** 164 * Sort all name-value pairs 165 */ 166 USPProto.sort = USPProto.sort || function() { 167 var dict = parseToDict(this.toString()), keys = [], k, i, j; 168 for (k in dict) { 169 keys.push(k); 170 } 171 keys.sort(); 172 173 for (i = 0; i < keys.length; i++) { 174 this['delete'](keys[i]); 175 } 176 for (i = 0; i < keys.length; i++) { 177 var key = keys[i], values = dict[key]; 178 for (j = 0; j < values.length; j++) { 179 this.append(key, values[j]); 180 } 181 } 182 }; 183 184 /** 185 * Returns an iterator allowing to go through all keys of 186 * the key/value pairs contained in this object. 187 * 188 * @returns {function} 189 */ 190 USPProto.keys = USPProto.keys || function() { 191 var items = []; 192 this.forEach(function(item, name) { 193 items.push(name); 194 }); 195 return makeIterator(items); 196 }; 197 198 /** 199 * Returns an iterator allowing to go through all values of 200 * the key/value pairs contained in this object. 201 * 202 * @returns {function} 203 */ 204 USPProto.values = USPProto.values || function() { 205 var items = []; 206 this.forEach(function(item) { 207 items.push(item); 208 }); 209 return makeIterator(items); 210 }; 211 212 /** 213 * Returns an iterator allowing to go through all key/value 214 * pairs contained in this object. 215 * 216 * @returns {function} 217 */ 218 USPProto.entries = USPProto.entries || function() { 219 var items = []; 220 this.forEach(function(item, name) { 221 items.push([name, item]); 222 }); 223 return makeIterator(items); 224 }; 225 226 227 if (iterable) {
vendor: 3,397 bytes, lines 228-341
228 USPProto[self.Symbol.iterator] = USPProto[self.Symbol.iterator] || USPProto.entries; 229 } 230 231 232 function encode(str) { 233 var replace = { 234 '!': '%21', 235 "'": '%27', 236 '(': '%28', 237 ')': '%29', 238 '~': '%7E', 239 '%20': '+', 240 '%00': '\x00' 241 }; 242 return encodeURIComponent(str).replace(/[!'\(\)~]|%20|%00/g, function(match) { 243 return replace[match]; 244 }); 245 } 246 247 function decode(str) { 248 return str 249 .replace(/[ +]/g, '%20') 250 .replace(/(%[a-f0-9]{2})+/ig, function(match) { 251 return decodeURIComponent(match); 252 }); 253 } 254 255 function makeIterator(arr) { 256 var iterator = { 257 next: function() { 258 var value = arr.shift(); 259 return {done: value === undefined, value: value}; 260 } 261 }; 262 263 if (iterable) { 264 iterator[self.Symbol.iterator] = function() { 265 return iterator; 266 }; 267 } 268 269 return iterator; 270 } 271 272 function parseToDict(search) { 273 var dict = {}; 274 275 if (typeof search === "object") { 276 // if `search` is an array, treat it as a sequence 277 if (isArray(search)) { 278 for (var i = 0; i < search.length; i++) { 279 var item = search[i]; 280 if (isArray(item) && item.length === 2) { 281 appendTo(dict, item[0], item[1]); 282 } else { 283 throw new TypeError("Failed to construct 'URLSearchParams': Sequence initializer must only contain pair elements"); 284 } 285 } 286 287 } else { 288 for (var key in search) { 289 if (search.hasOwnProperty(key)) { 290 appendTo(dict, key, search[key]); 291 } 292 } 293 } 294 295 } else { 296 // remove first '?' 297 if (search.indexOf("?") === 0) { 298 search = search.slice(1); 299 } 300 301 var pairs = search.split("&"); 302 for (var j = 0; j < pairs.length; j++) { 303 var value = pairs [j], 304 index = value.indexOf('='); 305 306 if (-1 < index) { 307 appendTo(dict, decode(value.slice(0, index)), decode(value.slice(index + 1))); 308 309 } else { 310 if (value) { 311 appendTo(dict, decode(value), ''); 312 } 313 } 314 } 315 } 316 317 return dict; 318 } 319 320 function appendTo(dict, name, value) { 321 var val = typeof value === 'string' ? value : ( 322 value !== null && value !== undefined && typeof value.toString === 'function' ? value.toString() : JSON.stringify(value) 323 ); 324 325 // #47 Prevent using `hasOwnProperty` as a property name 326 if (hasOwnProperty(dict, name)) { 327 dict[name].push(val); 328 } else { 329 dict[name] = [val]; 330 } 331 } 332 333 function isArray(val) { 334 return !!val && '[object Array]' === Object.prototype.toString.call(val); 335 } 336 337 function hasOwnProperty(obj, prop) { 338 return Object.prototype.hasOwnProperty.call(obj, prop); 339 } 340 341})(typeof global !== 'undefined' ? global : (typeof window !== 'undefined' ? window : this));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.