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 : 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 prototype = URLSearchParamsPolyfill.prototype, 18 iterable = !!(self.Symbol && self.Symbol.iterator); 19 20 if (nativeURLSearchParams && isSupportObjectConstructor && decodesPlusesCorrectly) { 21 return; 22 } 23 24 25 /** 26 * Make a URLSearchParams instance 27 * 28 * @param {object|string|URLSearchParams} search 29 * @constructor 30 */ 31 function URLSearchParamsPolyfill(search) { 32 search = search || ""; 33 34 // support construct object with another URLSearchParams instance 35 if (search instanceof URLSearchParams || search instanceof URLSearchParamsPolyfill) { 36 search = search.toString(); 37 } 38 this [__URLSearchParams__] = parseToDict(search); 39 } 40 41 42 /** 43 * Appends a specified key/value pair as a new search parameter. 44 * 45 * @param {string} name 46 * @param {string} value 47 */ 48 prototype.append = function(name, value) { 49 appendTo(this [__URLSearchParams__], name, value); 50 }; 51 52 /** 53 * Deletes the given search parameter, and its associated value, 54 * from the list of all search parameters. 55 * 56 * @param {string} name 57 */ 58 prototype.delete = function(name) { 59 delete this [__URLSearchParams__] [name]; 60 }; 61 62 /** 63 * Returns the first value associated to the given search parameter. 64 * 65 * @param {string} name 66 * @returns {string|null} 67 */ 68 prototype.get = function(name) { 69 var dict = this [__URLSearchParams__]; 70 return name in dict ? dict[name][0] : null; 71 }; 72 73 /** 74 * Returns all the values association with a given search parameter. 75 * 76 * @param {string} name 77 * @returns {Array} 78 */ 79 prototype.getAll = function(name) { 80 var dict = this [__URLSearchParams__]; 81 return name in dict ? dict [name].slice(0) : []; 82 }; 83 84 /** 85 * Returns a Boolean indicating if such a search parameter exists. 86 * 87 * @param {string} name 88 * @returns {boolean} 89 */ 90 prototype.has = function(name) { 91 return name in this [__URLSearchParams__]; 92 }; 93 94 /** 95 * Sets the value associated to a given search parameter to 96 * the given value. If there were several values, delete the 97 * others. 98 * 99 * @param {string} name 100 * @param {string} value 101 */ 102 prototype.set = function set(name, value) { 103 this [__URLSearchParams__][name] = ['' + value]; 104 }; 105 106 /** 107 * Returns a string containg a query string suitable for use in a URL. 108 * 109 * @returns {string} 110 */ 111 prototype.toString = function() { 112 var dict = this[__URLSearchParams__], query = [], i, key, name, value; 113 for (key in dict) { 114 name = encode(key); 115 for (i = 0, value = dict[key]; i < value.length; i++) { 116 query.push(name + '=' + encode(value[i])); 117 } 118 } 119 return query.join('&'); 120 }; 121 122 // There is a bug in Safari 10.1 and `Proxy`ing it is not enough. 123 var forSureUsePolyfill = !decodesPlusesCorrectly; 124 var useProxy = (!forSureUsePolyfill && nativeURLSearchParams && !isSupportObjectConstructor && self.Proxy) 125 /* 126 * Apply polifill to global object and append other prototype into it 127 */ 128 self.URLSearchParams = useProxy ? 129 // Safari 10.0 doesn't support Proxy, so it won't extend URLSearchParams on safari 10.0 130 new Proxy(nativeURLSearchParams, { 131 construct: function(target, args) { 132 return new target((new URLSearchParamsPolyfill(args[0]).toString())); 133 } 134 }) : 135 URLSearchParamsPolyfill; 136 137 138 var USPProto = self.URLSearchParams.prototype; 139 140 USPProto.polyfill = true; 141 142 /** 143 * 144 * @param {function} callback 145 * @param {object} thisArg 146 */ 147 USPProto.forEach = USPProto.forEach || function(callback, thisArg) { 148 var dict = parseToDict(this.toString()); 149 Object.getOwnPropertyNames(dict).forEach(function(name) { 150 dict[name].forEach(function(value) { 151 callback.call(thisArg, value, name, this); 152 }, this); 153 }, this); 154 }; 155 156 /** 157 * Sort all name-value pairs 158 */ 159 USPProto.sort = USPProto.sort || function() { 160 var dict = parseToDict(this.toString()), keys = [], k, i, j; 161 for (k in dict) { 162 keys.push(k); 163 } 164 keys.sort(); 165 166 for (i = 0; i < keys.length; i++) { 167 this.delete(keys[i]); 168 } 169 for (i = 0; i < keys.length; i++) { 170 var key = keys[i], values = dict[key]; 171 for (j = 0; j < values.length; j++) { 172 this.append(key, values[j]); 173 } 174 } 175 }; 176 177 /** 178 * Returns an iterator allowing to go through all keys of 179 * the key/value pairs contained in this object. 180 * 181 * @returns {function} 182 */ 183 USPProto.keys = USPProto.keys || function() { 184 var items = []; 185 this.forEach(function(item, name) { 186 items.push(name); 187 }); 188 return makeIterator(items); 189 }; 190 191 /** 192 * Returns an iterator allowing to go through all values of 193 * the key/value pairs contained in this object. 194 * 195 * @returns {function} 196 */ 197 USPProto.values = USPProto.values || function() { 198 var items = []; 199 this.forEach(function(item) { 200 items.push(item); 201 }); 202 return makeIterator(items); 203 }; 204 205 /** 206 * Returns an iterator allowing to go through all key/value 207 * pairs contained in this object. 208 * 209 * @returns {function} 210 */ 211 USPProto.entries = USPProto.entries || function() { 212 var items = []; 213 this.forEach(function(item, name) { 214 items.push([name, item]); 215 }); 216 return makeIterator(items); 217 }; 218 219 220 if (iterable) {
221 USPProto[self.Symbol.iterator] = USPProto[self.Symbol.iterator] || USPProto.entries; 222 } 223 224 225 function encode(str) { 226 var replace = { 227 '!': '%21', 228 "'": '%27', 229 '(': '%28', 230 ')': '%29', 231 '~': '%7E', 232 '%20': '+', 233 '%00': '\x00' 234 }; 235 return encodeURIComponent(str).replace(/[!'\(\)~]|%20|%00/g, function(match) { 236 return replace[match]; 237 }); 238 } 239 240 function decode(str) { 241 return decodeURIComponent(str.replace(/\+/g, ' ')); 242 } 243 244 function makeIterator(arr) { 245 var iterator = { 246 next: function() { 247 var value = arr.shift(); 248 return {done: value === undefined, value: value}; 249 } 250 }; 251 252 if (iterable) { 253 iterator[self.Symbol.iterator] = function() { 254 return iterator; 255 }; 256 } 257 258 return iterator; 259 } 260 261 function parseToDict(search) { 262 var dict = {}; 263 264 if (typeof search === "object") { 265 for (var key in search) { 266 if (search.hasOwnProperty(key)) { 267 appendTo(dict, key, search[key]) 268 } 269 } 270 271 } else { 272 // remove first '?' 273 if (search.indexOf("?") === 0) { 274 search = search.slice(1); 275 } 276 277 var pairs = search.split("&"); 278 for (var j = 0; j < pairs.length; j++) { 279 var value = pairs [j], 280 index = value.indexOf('='); 281 282 if (-1 < index) { 283 appendTo(dict, decode(value.slice(0, index)), decode(value.slice(index + 1))); 284 285 } else { 286 if (value) { 287 appendTo(dict, decode(value), ''); 288 } 289 } 290 } 291 } 292 293 return dict; 294 } 295 296 function appendTo(dict, name, value) { 297 var val = typeof value === 'string' ? value : ( 298 value !== null && typeof value.toString === 'function' ? value.toString() : JSON.stringify(value) 299 ) 300 301 if (name in dict) { 302 dict[name].push(val); 303 } else { 304 dict[name] = [val]; 305 } 306 } 307 308})(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.