376 lines
11 KiB
JavaScript
376 lines
11 KiB
JavaScript
/*! (c) Andrea Giammarchi - ISC */
|
|
var self = this || /* istanbul ignore next */ {};
|
|
try {
|
|
(function (URLSearchParams, plus) {
|
|
if (
|
|
new URLSearchParams('q=%2B').get('q') !== plus ||
|
|
new URLSearchParams({q: plus}).get('q') !== plus ||
|
|
new URLSearchParams([['q', plus]]).get('q') !== plus ||
|
|
new URLSearchParams('q=\n').toString() !== 'q=%0A' ||
|
|
new URLSearchParams({q: ' &'}).toString() !== 'q=+%26' ||
|
|
new URLSearchParams({q: '%zx'}).toString() !== 'q=%25zx'
|
|
)
|
|
throw URLSearchParams;
|
|
self.URLSearchParams = URLSearchParams;
|
|
}(URLSearchParams, '+'));
|
|
} catch(URLSearchParams) {
|
|
(function (Object, String, isArray) {'use strict';
|
|
var create = Object.create;
|
|
var defineProperty = Object.defineProperty;
|
|
var find = /[!'\(\)~]|%20|%00/g;
|
|
var findPercentSign = /%(?![0-9a-fA-F]{2})/g;
|
|
var plus = /\+/g;
|
|
var replace = {
|
|
'!': '%21',
|
|
"'": '%27',
|
|
'(': '%28',
|
|
')': '%29',
|
|
'~': '%7E',
|
|
'%20': '+',
|
|
'%00': '\x00'
|
|
};
|
|
var proto = {
|
|
append: function (key, value) {
|
|
appendTo(this._ungap, key, value);
|
|
},
|
|
delete: function (key) {
|
|
delete this._ungap[key];
|
|
},
|
|
get: function (key) {
|
|
return this.has(key) ? this._ungap[key][0] : null;
|
|
},
|
|
getAll: function (key) {
|
|
return this.has(key) ? this._ungap[key].slice(0) : [];
|
|
},
|
|
has: function (key) {
|
|
return key in this._ungap;
|
|
},
|
|
set: function (key, value) {
|
|
this._ungap[key] = [String(value)];
|
|
},
|
|
forEach: function (callback, thisArg) {
|
|
var self = this;
|
|
for (var key in self._ungap)
|
|
self._ungap[key].forEach(invoke, key);
|
|
function invoke(value) {
|
|
callback.call(thisArg, value, String(key), self);
|
|
}
|
|
},
|
|
toJSON: function () {
|
|
return {};
|
|
},
|
|
toString: function () {
|
|
var query = [];
|
|
for (var key in this._ungap) {
|
|
var encoded = encode(key);
|
|
for (var
|
|
i = 0,
|
|
value = this._ungap[key];
|
|
i < value.length; i++
|
|
) {
|
|
query.push(encoded + '=' + encode(value[i]));
|
|
}
|
|
}
|
|
return query.join('&');
|
|
}
|
|
};
|
|
for (var key in proto)
|
|
defineProperty(URLSearchParams.prototype, key, {
|
|
configurable: true,
|
|
writable: true,
|
|
value: proto[key]
|
|
});
|
|
self.URLSearchParams = URLSearchParams;
|
|
function URLSearchParams(query) {
|
|
var dict = create(null);
|
|
defineProperty(this, '_ungap', {value: dict});
|
|
switch (true) {
|
|
case !query:
|
|
break;
|
|
case typeof query === 'string':
|
|
if (query.charAt(0) === '?') {
|
|
query = query.slice(1);
|
|
}
|
|
for (var
|
|
pairs = query.split('&'),
|
|
i = 0,
|
|
length = pairs.length; i < length; i++
|
|
) {
|
|
var value = pairs[i];
|
|
var index = value.indexOf('=');
|
|
if (-1 < index) {
|
|
appendTo(
|
|
dict,
|
|
decode(value.slice(0, index)),
|
|
decode(value.slice(index + 1))
|
|
);
|
|
} else if (value.length){
|
|
appendTo(
|
|
dict,
|
|
decode(value),
|
|
''
|
|
);
|
|
}
|
|
}
|
|
break;
|
|
case isArray(query):
|
|
for (var
|
|
i = 0,
|
|
length = query.length; i < length; i++
|
|
) {
|
|
var value = query[i];
|
|
appendTo(dict, value[0], value[1]);
|
|
}
|
|
break;
|
|
case 'forEach' in query:
|
|
query.forEach(addEach, dict);
|
|
break;
|
|
default:
|
|
for (var key in query)
|
|
appendTo(dict, key, query[key]);
|
|
}
|
|
}
|
|
|
|
function addEach(value, key) {
|
|
appendTo(this, key, value);
|
|
}
|
|
|
|
function appendTo(dict, key, value) {
|
|
var res = isArray(value) ? value.join(',') : value;
|
|
if (key in dict)
|
|
dict[key].push(res);
|
|
else
|
|
dict[key] = [res];
|
|
}
|
|
|
|
function decode(str) {
|
|
return decodeURIComponent(str.replace(findPercentSign, '%25').replace(plus, ' '));
|
|
}
|
|
|
|
function encode(str) {
|
|
return encodeURIComponent(str).replace(find, replacer);
|
|
}
|
|
|
|
function replacer(match) {
|
|
return replace[match];
|
|
}
|
|
|
|
}(Object, String, Array.isArray));
|
|
}
|
|
|
|
(function (URLSearchParamsProto) {
|
|
|
|
var iterable = false;
|
|
try { iterable = !!Symbol.iterator; } catch (o_O) {}
|
|
|
|
/* istanbul ignore else */
|
|
if (!('forEach' in URLSearchParamsProto)) {
|
|
URLSearchParamsProto.forEach = function forEach(callback, thisArg) {
|
|
var self = this;
|
|
var names = Object.create(null);
|
|
this.toString()
|
|
.replace(/=[\s\S]*?(?:&|$)/g, '=')
|
|
.split('=')
|
|
.forEach(function (name) {
|
|
if (!name.length || name in names)
|
|
return;
|
|
(names[name] = self.getAll(name)).forEach(function(value) {
|
|
callback.call(thisArg, value, name, self);
|
|
});
|
|
});
|
|
};
|
|
}
|
|
|
|
/* istanbul ignore else */
|
|
if (!('keys' in URLSearchParamsProto)) {
|
|
URLSearchParamsProto.keys = function keys() {
|
|
return iterator(this, function(value, key) { this.push(key); });
|
|
};
|
|
}
|
|
|
|
/* istanbul ignore else */
|
|
if (!('values' in URLSearchParamsProto)) {
|
|
URLSearchParamsProto.values = function values() {
|
|
return iterator(this, function(value, key) { this.push(value); });
|
|
};
|
|
}
|
|
|
|
/* istanbul ignore else */
|
|
if (!('entries' in URLSearchParamsProto)) {
|
|
URLSearchParamsProto.entries = function entries() {
|
|
return iterator(this, function(value, key) { this.push([key, value]); });
|
|
};
|
|
}
|
|
|
|
/* istanbul ignore else */
|
|
if (iterable && !(Symbol.iterator in URLSearchParamsProto)) {
|
|
URLSearchParamsProto[Symbol.iterator] = URLSearchParamsProto.entries;
|
|
}
|
|
|
|
/* istanbul ignore else */
|
|
if (!('sort' in URLSearchParamsProto)) {
|
|
URLSearchParamsProto.sort = function sort() {
|
|
var
|
|
entries = this.entries(),
|
|
entry = entries.next(),
|
|
done = entry.done,
|
|
keys = [],
|
|
values = Object.create(null),
|
|
i, key, value
|
|
;
|
|
while (!done) {
|
|
value = entry.value;
|
|
key = value[0];
|
|
keys.push(key);
|
|
if (!(key in values)) {
|
|
values[key] = [];
|
|
}
|
|
values[key].push(value[1]);
|
|
entry = entries.next();
|
|
done = entry.done;
|
|
}
|
|
// not the champion in efficiency
|
|
// but these two bits just do the job
|
|
keys.sort();
|
|
for (i = 0; i < keys.length; i++) {
|
|
this.delete(keys[i]);
|
|
}
|
|
for (i = 0; i < keys.length; i++) {
|
|
key = keys[i];
|
|
this.append(key, values[key].shift());
|
|
}
|
|
};
|
|
}
|
|
|
|
function iterator(self, callback) {
|
|
var items = [];
|
|
self.forEach(callback, items);
|
|
return iterable ?
|
|
items[Symbol.iterator]() :
|
|
{
|
|
next: function() {
|
|
var value = items.shift();
|
|
return {done: value === undefined, value: value};
|
|
}
|
|
};
|
|
}
|
|
|
|
/* istanbul ignore next */
|
|
(function (Object) {
|
|
var
|
|
dP = Object.defineProperty,
|
|
gOPD = Object.getOwnPropertyDescriptor,
|
|
createSearchParamsPollute = function (search) {
|
|
function append(name, value) {
|
|
URLSearchParamsProto.append.call(this, name, value);
|
|
name = this.toString();
|
|
search.set.call(this._usp, name ? ('?' + name) : '');
|
|
}
|
|
function del(name) {
|
|
URLSearchParamsProto.delete.call(this, name);
|
|
name = this.toString();
|
|
search.set.call(this._usp, name ? ('?' + name) : '');
|
|
}
|
|
function set(name, value) {
|
|
URLSearchParamsProto.set.call(this, name, value);
|
|
name = this.toString();
|
|
search.set.call(this._usp, name ? ('?' + name) : '');
|
|
}
|
|
return function (sp, value) {
|
|
sp.append = append;
|
|
sp.delete = del;
|
|
sp.set = set;
|
|
return dP(sp, '_usp', {
|
|
configurable: true,
|
|
writable: true,
|
|
value: value
|
|
});
|
|
};
|
|
},
|
|
createSearchParamsCreate = function (polluteSearchParams) {
|
|
return function (obj, sp) {
|
|
dP(
|
|
obj, '_searchParams', {
|
|
configurable: true,
|
|
writable: true,
|
|
value: polluteSearchParams(sp, obj)
|
|
}
|
|
);
|
|
return sp;
|
|
};
|
|
},
|
|
updateSearchParams = function (sp) {
|
|
var append = sp.append;
|
|
sp.append = URLSearchParamsProto.append;
|
|
URLSearchParams.call(sp, sp._usp.search.slice(1));
|
|
sp.append = append;
|
|
},
|
|
verifySearchParams = function (obj, Class) {
|
|
if (!(obj instanceof Class)) throw new TypeError(
|
|
"'searchParams' accessed on an object that " +
|
|
"does not implement interface " + Class.name
|
|
);
|
|
},
|
|
upgradeClass = function (Class) {
|
|
var
|
|
ClassProto = Class.prototype,
|
|
searchParams = gOPD(ClassProto, 'searchParams'),
|
|
href = gOPD(ClassProto, 'href'),
|
|
search = gOPD(ClassProto, 'search'),
|
|
createSearchParams
|
|
;
|
|
if (!searchParams && search && search.set) {
|
|
createSearchParams = createSearchParamsCreate(
|
|
createSearchParamsPollute(search)
|
|
);
|
|
Object.defineProperties(
|
|
ClassProto,
|
|
{
|
|
href: {
|
|
get: function () {
|
|
return href.get.call(this);
|
|
},
|
|
set: function (value) {
|
|
var sp = this._searchParams;
|
|
href.set.call(this, value);
|
|
if (sp) updateSearchParams(sp);
|
|
}
|
|
},
|
|
search: {
|
|
get: function () {
|
|
return search.get.call(this);
|
|
},
|
|
set: function (value) {
|
|
var sp = this._searchParams;
|
|
search.set.call(this, value);
|
|
if (sp) updateSearchParams(sp);
|
|
}
|
|
},
|
|
searchParams: {
|
|
get: function () {
|
|
verifySearchParams(this, Class);
|
|
return this._searchParams || createSearchParams(
|
|
this,
|
|
new URLSearchParams(this.search.slice(1))
|
|
);
|
|
},
|
|
set: function (sp) {
|
|
verifySearchParams(this, Class);
|
|
createSearchParams(this, sp);
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
}
|
|
;
|
|
try {
|
|
upgradeClass(HTMLAnchorElement);
|
|
if (/^function|object$/.test(typeof URL) && URL.prototype)
|
|
upgradeClass(URL);
|
|
} catch (meh) {}
|
|
}(Object));
|
|
|
|
}(self.URLSearchParams.prototype, Object));
|
|
export default self.URLSearchParams;
|