PageSourceSearch

https://xlactating.com/vpapi/polyfill/url.js

js xlactating.com collected 2026-09-30 02:50:22 UTC 11,742 bytes, 473 lines download raw bytes

vendor: 11,742 bytes, lines 1-473
1//
2// URL polyfill from https://github.com/lifaon74/url-polyfill
3//
4
5(function (global) {
6	/**
7	 * Polyfill URLSearchParams
8	 *
9	 * Inspired from : https://github.com/WebReflection/url-search-params/blob/master/src/url-search-params.js
10	 */
11
12	var checkIfIteratorIsSupported = function () {
13		try {
14			return !!Symbol.iterator;
15		} catch (error) {
16			return false;
17		}
18	};
19
20
21	var iteratorSupported = checkIfIteratorIsSupported();
22
23	var createIterator = function (items) {
24		var iterator = {
25			next: function () {
26				var value = items.shift();
27				return { done: value === void 0, value: value };
28			}
29		};
30
31		if (iteratorSupported) {
32			iterator[Symbol.iterator] = function () {
33				return iterator;
34			};
35		}
36
37		return iterator;
38	};
39
40	/**
41	 * Search param name and values should be encoded according to https://url.spec.whatwg.org/#urlencoded-serializing
42	 * encodeURIComponent() produces the same result except encoding spaces as `%20` instead of `+`.
43	 */
44	var serializeParam = function (value) {
45		return encodeURIComponent(value).replace(/%20/g, '+');
46	};
47
48	var deserializeParam = function (value) {
49		return decodeURIComponent(String(value).replace(/\+/g, ' '));
50	};
51
52	var polyfillURLSearchParams = function () {
53
54		var URLSearchParams = function (searchString) {
55			Object.defineProperty(this, '_entries', { writable: true, value: {} });
56			var typeofSearchString = typeof searchString;
57
58			if (typeofSearchString === 'undefined') {
59				// do nothing
60			} else if (typeofSearchString === 'string') {
61				if (searchString !== '') {
62					this._fromString(searchString);
63				}
64			} else if (searchString instanceof URLSearchParams) {
65				var _this = this;
66				searchString.forEach(function (value, name) {
67					_this.append(name, value);
68				});
69			} else if ((searchString !== null) && (typeofSearchString === 'object')) {
70				if (Object.prototype.toString.call(searchString) === '[object Array]') {
71					for (var i = 0; i < searchString.length; i++) {
72						var entry = searchString[i];
73						if ((Object.prototype.toString.call(entry) === '[object Array]') || (entry.length !== 2)) {
74							this.append(entry[0], entry[1]);
75						} else {
76							throw new TypeError('Expected [string, any] as entry at index ' + i + ' of URLSearchParams\'s input');
77						}
78					}
79				} else {
80					for (var key in searchString) {
81						if (searchString.hasOwnProperty(key)) {
82							this.append(key, searchString[key]);
83						}
84					}
85				}
86			} else {
87				throw new TypeError('Unsupported input\'s type for URLSearchParams');
88			}
89		};
90
91		var proto = URLSearchParams.prototype;
92
93		proto.append = function (name, value) {
94			if (name in this._entries) {
95				this._entries[name].push(String(value));
96			} else {
97				this._entries[name] = [String(value)];
98			}
99		};
100
101		proto.delete = function (name) {
102			delete this._entries[name];
103		};
104
105		proto.get = function (name) {
106			return (name in this._entries) ? this._entries[name][0] : null;
107		};
108
109		proto.getAll = function (name) {
110			return (name in this._entries) ? this._entries[name].slice(0) : [];
111		};
112
113		proto.has = function (name) {
114			return (name in this._entries);
115		};
116
117		proto.set = function (name, value) {
118			this._entries[name] = [String(value)];
119		};
120
121		proto.forEach = function (callback, thisArg) {
122			var entries;
123			for (var name in this._entries) {
124				if (this._entries.hasOwnProperty(name)) {
125					entries = this._entries[name];
126					for (var i = 0; i < entries.length; i++) {
127						callback.call(thisArg, entries[i], name, this);
128					}
129				}
130			}
131		};
132
133		proto.keys = function () {
134			var items = [];
135			this.forEach(function (value, name) {
136				items.push(name);
137			});
138			return createIterator(items);
139		};
140
141		proto.values = function () {
142			var items = [];
143			this.forEach(function (value) {
144				items.push(value);
145			});
146			return createIterator(items);
147		};
148
149		proto.entries = function () {
150			var items = [];
151			this.forEach(function (value, name) {
152				items.push([name, value]);
153			});
154			return createIterator(items);
155		};
156
157		if (iteratorSupported) {
158			proto[Symbol.iterator] = proto.entries;
159		}
160
161		proto.toString = function () {
162			var searchArray = [];
163			this.forEach(function (value, name) {
164				searchArray.push(serializeParam(name) + '=' + serializeParam(value));
165			});
166			return searchArray.join('&');
167		};
168
169
170		global.URLSearchParams = URLSearchParams;
171	};
172
173	if (!('URLSearchParams' in global) || (new global.URLSearchParams('?a=1').toString() !== 'a=1')) {
174		polyfillURLSearchParams();
175	}
176
177	var proto = global.URLSearchParams.prototype;
178
179	if (typeof proto.sort !== 'function') {
180		proto.sort = function () {
181			var _this = this;
182			var items = [];
183			this.forEach(function (value, name) {
184				items.push([name, value]);
185				if (!_this._entries) {
186					_this.delete(name);
187				}
188			});
189			items.sort(function (a, b) {
190				if (a[0] < b[0]) {
191					return -1;
192				} else if (a[0] > b[0]) {
193					return +1;
194				} else {
195					return 0;
196				}
197			});
198			if (_this._entries) { // force reset because IE keeps keys index
199				_this._entries = {};
200			}
201			for (var i = 0; i < items.length; i++) {
202				this.append(items[i][0], items[i][1]);
203			}
204		};
205	}
206
207	if (typeof proto._fromString !== 'function') {
208		Object.defineProperty(proto, '_fromString', {
209			enumerable: false,
210			configurable: false,
211			writable: false,
212			value: function (searchString) {
213				if (this._entries) {
214					this._entries = {};
215				} else {
216					var keys = [];
217					this.forEach(function (value, name) {
218						keys.push(name);
219					});
220					for (var i = 0; i < keys.length; i++) {
221						this.delete(keys[i]);
222					}
223				}
224
225				searchString = searchString.replace(/^\?/, '');
226				var attributes = searchString.split('&');
227				var attribute;
228				for (var i = 0; i < attributes.length; i++) {
229					attribute = attributes[i].split('=');
230					this.append(
231						deserializeParam(attribute[0]),
232						(attribute.length > 1) ? deserializeParam(attribute[1]) : ''
233					);
234				}
235			}
236		});
237	}
238
239	// HTMLAnchorElement
240
241})(
242	(typeof global !== 'undefined') ? global
243		: ((typeof window !== 'undefined') ? window
244			: ((typeof self !== 'undefined') ? self : this))
245);
246
247(function (global) {
248	/**
249	 * Polyfill URL
250	 *
251	 * Inspired from : https://github.com/arv/DOM-URL-Polyfill/blob/master/src/url.js
252	 */
253
254	var checkIfURLIsSupported = function () {
255		try {
256			var u = new global.URL('b', 'http://a');
257			u.pathname = 'c%20d';
258			return (u.href === 'http://a/c%20d') && u.searchParams;
259		} catch (e) {
260			return false;
261		}
262	};
263
264
265	var polyfillURL = function () {
266		var _URL = global.URL;
267
268		var URL = function (url, base) {
269			if (typeof url !== 'string') url = String(url);
270
271			// Only create another document if the base is different from current location.
272			var doc = document, baseElement;
273			if (base && (global.location === void 0 || base !== global.location.href)) {
274				doc = document.implementation.createHTMLDocument('');
275				baseElement = doc.createElement('base');
276				baseElement.href = base;
277				doc.head.appendChild(baseElement);
278				try {
279					if (baseElement.href.indexOf(base) !== 0) throw new Error(baseElement.href);
280				} catch (err) {
281					throw new Error('URL unable to set base ' + base + ' due to ' + err);
282				}
283			}
284
285			var anchorElement = doc.createElement('a');
286			anchorElement.href = url;
287			if (baseElement) {
288				doc.body.appendChild(anchorElement);
289				anchorElement.href = anchorElement.href; // force href to refresh
290			}
291
292			if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) {
293				throw new TypeError('Invalid URL');
294			}
295
296			Object.defineProperty(this, '_anchorElement', {
297				value: anchorElement
298			});
299
300
301			// create a linked searchParams which reflect its changes on URL
302			var searchParams = new global.URLSearchParams(this.search);
303			var enableSearchUpdate = true;
304			var enableSearchParamsUpdate = true;
305			var _this = this;
306			['append', 'delete', 'set'].forEach(function (methodName) {
307				var method = searchParams[methodName];
308				searchParams[methodName] = function () {
309					method.apply(searchParams, arguments);
310					if (enableSearchUpdate) {
311						enableSearchParamsUpdate = false;
312						_this.search = searchParams.toString();
313						enableSearchParamsUpdate = true;
314					}
315				};
316			});
317
318			Object.defineProperty(this, 'searchParams', {
319				value: searchParams,
320				enumerable: true
321			});
322
323			var search = void 0;
324			Object.defineProperty(this, '_updateSearchParams', {
325				enumerable: false,
326				configurable: false,
327				writable: false,
328				value: function () {
329					if (this.search !== search) {
330						search = this.search;
331						if (enableSearchParamsUpdate) {
332							enableSearchUpdate = false;
333							this.searchParams._fromString(this.search);
334							enableSearchUpdate = true;
335						}
336					}
337				}
338			});
339		};
340
341		var proto = URL.prototype;
342
343		var linkURLWithAnchorAttribute = function (attributeName) {
344			Object.defineProperty(proto, attributeName, {
345				get: function () {
346					return this._anchorElement[attributeName];
347				},
348				set: function (value) {
349					this._anchorElement[attributeName] = value;
350				},
351				enumerable: true
352			});
353		};
354
355		['hash', 'host', 'hostname', 'port', 'protocol']
356			.forEach(function (attributeName) {
357				linkURLWithAnchorAttribute(attributeName);
358			});
359
360		Object.defineProperty(proto, 'search', {
361			get: function () {
362				return this._anchorElement['search'];
363			},
364			set: function (value) {
365				this._anchorElement['search'] = value;
366				this._updateSearchParams();
367			},
368			enumerable: true
369		});
370
371		Object.defineProperties(proto, {
372
373			'toString': {
374				get: function () {
375					var _this = this;
376					return function () {
377						return _this.href;
378					};
379				}
380			},
381
382			'href': {
383				get: function () {
384					return this._anchorElement.href.replace(/\?$/, '');
385				},
386				set: function (value) {
387					this._anchorElement.href = value;
388					this._updateSearchParams();
389				},
390				enumerable: true
391			},
392
393			'pathname': {
394				get: function () {
395					return this._anchorElement.pathname.replace(/(^\/?)/, '/');
396				},
397				set: function (value) {
398					this._anchorElement.pathname = value;
399				},
400				enumerable: true
401			},
402
403			'origin': {
404				get: function () {
405					// get expected port from protocol
406					var expectedPort = { 'http:': 80, 'https:': 443, 'ftp:': 21 }[this._anchorElement.protocol];
407					// add port to origin if, expected port is different than actual port
408					// and it is not empty f.e http://foo:8080
409					// 8080 != 80 && 8080 != ''
410					var addPortToOrigin = this._anchorElement.port != expectedPort &&
411						this._anchorElement.port !== '';
412
413					return this._anchorElement.protocol +
414						'//' +
415						this._anchorElement.hostname +
416						(addPortToOrigin ? (':' + this._anchorElement.port) : '');
417				},
418				enumerable: true
419			},
420
421			'password': { // TODO
422				get: function () {
423					return '';
424				},
425				set: function (value) {
426				},
427				enumerable: true
428			},
429
430			'username': { // TODO
431				get: function () {
432					return '';
433				},
434				set: function (value) {
435				},
436				enumerable: true
437			},
438		});
439
440		URL.createObjectURL = function (blob) {
441			return _URL.createObjectURL.apply(_URL, arguments);
442		};
443
444		URL.revokeObjectURL = function (url) {
445			return _URL.revokeObjectURL.apply(_URL, arguments);
446		};
447
448		global.URL = URL;
449
450	};
451
452	if (!checkIfURLIsSupported()) {
453		polyfillURL();
454	}
455
456	if ((global.location !== void 0) && !('origin' in global.location)) {
457		var getOrigin = function () {
458			return global.location.protocol + '//' + global.location.hostname + (global.location.port ? (':' + global.location.port) : '');
459		};
460
461		try {
462			Object.defineProperty(global.location, 'origin', {
463				get: getOrigin,
464				enumerable: true
465			});
466		} catch (e) {
467			setInterval(function () {
468				global.location.origin = getOrigin();
469			}, 100);
470		}
471	}
472
473})(window);

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.