2 // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env`
3 require('../modules/es.array.iterator');
4 var $ = require('../internals/export');
5 var global = require('../internals/global');
6 var getBuiltIn = require('../internals/get-built-in');
7 var call = require('../internals/function-call');
8 var uncurryThis = require('../internals/function-uncurry-this');
9 var USE_NATIVE_URL = require('../internals/native-url');
10 var redefine = require('../internals/redefine');
11 var redefineAll = require('../internals/redefine-all');
12 var setToStringTag = require('../internals/set-to-string-tag');
13 var createIteratorConstructor = require('../internals/create-iterator-constructor');
14 var InternalStateModule = require('../internals/internal-state');
15 var anInstance = require('../internals/an-instance');
16 var isCallable = require('../internals/is-callable');
17 var hasOwn = require('../internals/has-own-property');
18 var bind = require('../internals/function-bind-context');
19 var classof = require('../internals/classof');
20 var anObject = require('../internals/an-object');
21 var isObject = require('../internals/is-object');
22 var $toString = require('../internals/to-string');
23 var create = require('../internals/object-create');
24 var createPropertyDescriptor = require('../internals/create-property-descriptor');
25 var getIterator = require('../internals/get-iterator');
26 var getIteratorMethod = require('../internals/get-iterator-method');
27 var wellKnownSymbol = require('../internals/well-known-symbol');
28 var arraySort = require('../internals/array-sort');
30 var ITERATOR = wellKnownSymbol('iterator');
31 var URL_SEARCH_PARAMS = 'URLSearchParams';
32 var URL_SEARCH_PARAMS_ITERATOR = URL_SEARCH_PARAMS + 'Iterator';
33 var setInternalState = InternalStateModule.set;
34 var getInternalParamsState = InternalStateModule.getterFor(URL_SEARCH_PARAMS);
35 var getInternalIteratorState = InternalStateModule.getterFor(URL_SEARCH_PARAMS_ITERATOR);
37 var n$Fetch = getBuiltIn('fetch');
38 var N$Request = getBuiltIn('Request');
39 var Headers = getBuiltIn('Headers');
40 var RequestPrototype = N$Request && N$Request.prototype;
41 var HeadersPrototype = Headers && Headers.prototype;
42 var RegExp = global.RegExp;
43 var TypeError = global.TypeError;
44 var decodeURIComponent = global.decodeURIComponent;
45 var encodeURIComponent = global.encodeURIComponent;
46 var charAt = uncurryThis(''.charAt);
47 var join = uncurryThis([].join);
48 var push = uncurryThis([].push);
49 var replace = uncurryThis(''.replace);
50 var shift = uncurryThis([].shift);
51 var splice = uncurryThis([].splice);
52 var split = uncurryThis(''.split);
53 var stringSlice = uncurryThis(''.slice);
56 var sequences = Array(4);
58 var percentSequence = function (bytes) {
59 return sequences[bytes - 1] || (sequences[bytes - 1] = RegExp('((?:%[\\da-f]{2}){' + bytes + '})', 'gi'));
62 var percentDecode = function (sequence) {
64 return decodeURIComponent(sequence);
70 var deserialize = function (it) {
71 var result = replace(it, plus, ' ');
74 return decodeURIComponent(result);
77 result = replace(result, percentSequence(bytes--), percentDecode);
83 var find = /[!'()~]|%20/g;
94 var replacer = function (match) {
95 return replacements[match];
98 var serialize = function (it) {
99 return replace(encodeURIComponent(it), find, replacer);
102 var validateArgumentsLength = function (passed, required) {
103 if (passed < required) throw TypeError('Not enough arguments');
106 var URLSearchParamsIterator = createIteratorConstructor(function Iterator(params, kind) {
107 setInternalState(this, {
108 type: URL_SEARCH_PARAMS_ITERATOR,
109 iterator: getIterator(getInternalParamsState(params).entries),
112 }, 'Iterator', function next() {
113 var state = getInternalIteratorState(this);
114 var kind = state.kind;
115 var step = state.iterator.next();
116 var entry = step.value;
118 step.value = kind === 'keys' ? entry.key : kind === 'values' ? entry.value : [entry.key, entry.value];
122 var URLSearchParamsState = function (init) {
126 if (init !== undefined) {
127 if (isObject(init)) this.parseObject(init);
128 else this.parseQuery(typeof init == 'string' ? charAt(init, 0) === '?' ? stringSlice(init, 1) : init : $toString(init));
132 URLSearchParamsState.prototype = {
133 type: URL_SEARCH_PARAMS,
134 bindURL: function (url) {
138 parseObject: function (object) {
139 var iteratorMethod = getIteratorMethod(object);
140 var iterator, next, step, entryIterator, entryNext, first, second;
142 if (iteratorMethod) {
143 iterator = getIterator(object, iteratorMethod);
144 next = iterator.next;
145 while (!(step = call(next, iterator)).done) {
146 entryIterator = getIterator(anObject(step.value));
147 entryNext = entryIterator.next;
149 (first = call(entryNext, entryIterator)).done ||
150 (second = call(entryNext, entryIterator)).done ||
151 !call(entryNext, entryIterator).done
152 ) throw TypeError('Expected sequence with length 2');
153 push(this.entries, { key: $toString(first.value), value: $toString(second.value) });
155 } else for (var key in object) if (hasOwn(object, key)) {
156 push(this.entries, { key: key, value: $toString(object[key]) });
159 parseQuery: function (query) {
161 var attributes = split(query, '&');
163 var attribute, entry;
164 while (index < attributes.length) {
165 attribute = attributes[index++];
166 if (attribute.length) {
167 entry = split(attribute, '=');
169 key: deserialize(shift(entry)),
170 value: deserialize(join(entry, '='))
176 serialize: function () {
177 var entries = this.entries;
181 while (index < entries.length) {
182 entry = entries[index++];
183 push(result, serialize(entry.key) + '=' + serialize(entry.value));
184 } return join(result, '&');
186 update: function () {
187 this.entries.length = 0;
188 this.parseQuery(this.url.query);
190 updateURL: function () {
191 if (this.url) this.url.update();
195 // `URLSearchParams` constructor
196 // https://url.spec.whatwg.org/#interface-urlsearchparams
197 var URLSearchParamsConstructor = function URLSearchParams(/* init */) {
198 anInstance(this, URLSearchParamsPrototype);
199 var init = arguments.length > 0 ? arguments[0] : undefined;
200 setInternalState(this, new URLSearchParamsState(init));
203 var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype;
205 redefineAll(URLSearchParamsPrototype, {
206 // `URLSearchParams.prototype.append` method
207 // https://url.spec.whatwg.org/#dom-urlsearchparams-append
208 append: function append(name, value) {
209 validateArgumentsLength(arguments.length, 2);
210 var state = getInternalParamsState(this);
211 push(state.entries, { key: $toString(name), value: $toString(value) });
214 // `URLSearchParams.prototype.delete` method
215 // https://url.spec.whatwg.org/#dom-urlsearchparams-delete
216 'delete': function (name) {
217 validateArgumentsLength(arguments.length, 1);
218 var state = getInternalParamsState(this);
219 var entries = state.entries;
220 var key = $toString(name);
222 while (index < entries.length) {
223 if (entries[index].key === key) splice(entries, index, 1);
228 // `URLSearchParams.prototype.get` method
229 // https://url.spec.whatwg.org/#dom-urlsearchparams-get
230 get: function get(name) {
231 validateArgumentsLength(arguments.length, 1);
232 var entries = getInternalParamsState(this).entries;
233 var key = $toString(name);
235 for (; index < entries.length; index++) {
236 if (entries[index].key === key) return entries[index].value;
240 // `URLSearchParams.prototype.getAll` method
241 // https://url.spec.whatwg.org/#dom-urlsearchparams-getall
242 getAll: function getAll(name) {
243 validateArgumentsLength(arguments.length, 1);
244 var entries = getInternalParamsState(this).entries;
245 var key = $toString(name);
248 for (; index < entries.length; index++) {
249 if (entries[index].key === key) push(result, entries[index].value);
253 // `URLSearchParams.prototype.has` method
254 // https://url.spec.whatwg.org/#dom-urlsearchparams-has
255 has: function has(name) {
256 validateArgumentsLength(arguments.length, 1);
257 var entries = getInternalParamsState(this).entries;
258 var key = $toString(name);
260 while (index < entries.length) {
261 if (entries[index++].key === key) return true;
265 // `URLSearchParams.prototype.set` method
266 // https://url.spec.whatwg.org/#dom-urlsearchparams-set
267 set: function set(name, value) {
268 validateArgumentsLength(arguments.length, 1);
269 var state = getInternalParamsState(this);
270 var entries = state.entries;
272 var key = $toString(name);
273 var val = $toString(value);
276 for (; index < entries.length; index++) {
277 entry = entries[index];
278 if (entry.key === key) {
279 if (found) splice(entries, index--, 1);
286 if (!found) push(entries, { key: key, value: val });
289 // `URLSearchParams.prototype.sort` method
290 // https://url.spec.whatwg.org/#dom-urlsearchparams-sort
291 sort: function sort() {
292 var state = getInternalParamsState(this);
293 arraySort(state.entries, function (a, b) {
294 return a.key > b.key ? 1 : -1;
298 // `URLSearchParams.prototype.forEach` method
299 forEach: function forEach(callback /* , thisArg */) {
300 var entries = getInternalParamsState(this).entries;
301 var boundFunction = bind(callback, arguments.length > 1 ? arguments[1] : undefined);
304 while (index < entries.length) {
305 entry = entries[index++];
306 boundFunction(entry.value, entry.key, this);
309 // `URLSearchParams.prototype.keys` method
310 keys: function keys() {
311 return new URLSearchParamsIterator(this, 'keys');
313 // `URLSearchParams.prototype.values` method
314 values: function values() {
315 return new URLSearchParamsIterator(this, 'values');
317 // `URLSearchParams.prototype.entries` method
318 entries: function entries() {
319 return new URLSearchParamsIterator(this, 'entries');
321 }, { enumerable: true });
323 // `URLSearchParams.prototype[@@iterator]` method
324 redefine(URLSearchParamsPrototype, ITERATOR, URLSearchParamsPrototype.entries, { name: 'entries' });
326 // `URLSearchParams.prototype.toString` method
327 // https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior
328 redefine(URLSearchParamsPrototype, 'toString', function toString() {
329 return getInternalParamsState(this).serialize();
330 }, { enumerable: true });
332 setToStringTag(URLSearchParamsConstructor, URL_SEARCH_PARAMS);
334 $({ global: true, forced: !USE_NATIVE_URL }, {
335 URLSearchParams: URLSearchParamsConstructor
338 // Wrap `fetch` and `Request` for correct work with polyfilled `URLSearchParams`
339 if (!USE_NATIVE_URL && isCallable(Headers)) {
340 var headersHas = uncurryThis(HeadersPrototype.has);
341 var headersSet = uncurryThis(HeadersPrototype.set);
343 var wrapRequestOptions = function (init) {
344 if (isObject(init)) {
345 var body = init.body;
347 if (classof(body) === URL_SEARCH_PARAMS) {
348 headers = init.headers ? new Headers(init.headers) : new Headers();
349 if (!headersHas(headers, 'content-type')) {
350 headersSet(headers, 'content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
352 return create(init, {
353 body: createPropertyDescriptor(0, $toString(body)),
354 headers: createPropertyDescriptor(0, headers)
360 if (isCallable(n$Fetch)) {
361 $({ global: true, enumerable: true, forced: true }, {
362 fetch: function fetch(input /* , init */) {
363 return n$Fetch(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});
368 if (isCallable(N$Request)) {
369 var RequestConstructor = function Request(input /* , init */) {
370 anInstance(this, RequestPrototype);
371 return new N$Request(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});
374 RequestPrototype.constructor = RequestConstructor;
375 RequestConstructor.prototype = RequestPrototype;
377 $({ global: true, forced: true }, {
378 Request: RequestConstructor
384 URLSearchParams: URLSearchParamsConstructor,
385 getState: getInternalParamsState