| | |
| | | 'use strict'; |
| | | // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env` |
| | | require('../modules/es.array.iterator'); |
| | | var $ = require('../internals/export'); |
| | | var getBuiltIn = require('../internals/get-built-in'); |
| | | var USE_NATIVE_URL = require('../internals/native-url'); |
| | | var redefine = require('../internals/redefine'); |
| | | var redefineAll = require('../internals/redefine-all'); |
| | | var setToStringTag = require('../internals/set-to-string-tag'); |
| | | var createIteratorConstructor = require('../internals/create-iterator-constructor'); |
| | | var InternalStateModule = require('../internals/internal-state'); |
| | | var anInstance = require('../internals/an-instance'); |
| | | var isCallable = require('../internals/is-callable'); |
| | | var hasOwn = require('../internals/has-own-property'); |
| | | var bind = require('../internals/function-bind-context'); |
| | | var classof = require('../internals/classof'); |
| | | var anObject = require('../internals/an-object'); |
| | | var isObject = require('../internals/is-object'); |
| | | var $toString = require('../internals/to-string'); |
| | | var create = require('../internals/object-create'); |
| | | var createPropertyDescriptor = require('../internals/create-property-descriptor'); |
| | | var getIterator = require('../internals/get-iterator'); |
| | | var getIteratorMethod = require('../internals/get-iterator-method'); |
| | | var wellKnownSymbol = require('../internals/well-known-symbol'); |
| | | |
| | | var nativeFetch = getBuiltIn('fetch'); |
| | | var NativeRequest = getBuiltIn('Request'); |
| | | var RequestPrototype = NativeRequest && NativeRequest.prototype; |
| | | var Headers = getBuiltIn('Headers'); |
| | | var ITERATOR = wellKnownSymbol('iterator'); |
| | | var URL_SEARCH_PARAMS = 'URLSearchParams'; |
| | | var URL_SEARCH_PARAMS_ITERATOR = URL_SEARCH_PARAMS + 'Iterator'; |
| | | var setInternalState = InternalStateModule.set; |
| | | var getInternalParamsState = InternalStateModule.getterFor(URL_SEARCH_PARAMS); |
| | | var getInternalIteratorState = InternalStateModule.getterFor(URL_SEARCH_PARAMS_ITERATOR); |
| | | |
| | | var plus = /\+/g; |
| | | var sequences = Array(4); |
| | | |
| | | var percentSequence = function (bytes) { |
| | | return sequences[bytes - 1] || (sequences[bytes - 1] = RegExp('((?:%[\\da-f]{2}){' + bytes + '})', 'gi')); |
| | | }; |
| | | |
| | | var percentDecode = function (sequence) { |
| | | try { |
| | | return decodeURIComponent(sequence); |
| | | } catch (error) { |
| | | return sequence; |
| | | } |
| | | }; |
| | | |
| | | var deserialize = function (it) { |
| | | var result = it.replace(plus, ' '); |
| | | var bytes = 4; |
| | | try { |
| | | return decodeURIComponent(result); |
| | | } catch (error) { |
| | | while (bytes) { |
| | | result = result.replace(percentSequence(bytes--), percentDecode); |
| | | } |
| | | return result; |
| | | } |
| | | }; |
| | | |
| | | var find = /[!'()~]|%20/g; |
| | | |
| | | var replace = { |
| | | '!': '%21', |
| | | "'": '%27', |
| | | '(': '%28', |
| | | ')': '%29', |
| | | '~': '%7E', |
| | | '%20': '+' |
| | | }; |
| | | |
| | | var replacer = function (match) { |
| | | return replace[match]; |
| | | }; |
| | | |
| | | var serialize = function (it) { |
| | | return encodeURIComponent(it).replace(find, replacer); |
| | | }; |
| | | |
| | | var parseSearchParams = function (result, query) { |
| | | if (query) { |
| | | var attributes = query.split('&'); |
| | | var index = 0; |
| | | var attribute, entry; |
| | | while (index < attributes.length) { |
| | | attribute = attributes[index++]; |
| | | if (attribute.length) { |
| | | entry = attribute.split('='); |
| | | result.push({ |
| | | key: deserialize(entry.shift()), |
| | | value: deserialize(entry.join('=')) |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | var updateSearchParams = function (query) { |
| | | this.entries.length = 0; |
| | | parseSearchParams(this.entries, query); |
| | | }; |
| | | |
| | | var validateArgumentsLength = function (passed, required) { |
| | | if (passed < required) throw TypeError('Not enough arguments'); |
| | | }; |
| | | |
| | | var URLSearchParamsIterator = createIteratorConstructor(function Iterator(params, kind) { |
| | | setInternalState(this, { |
| | | type: URL_SEARCH_PARAMS_ITERATOR, |
| | | iterator: getIterator(getInternalParamsState(params).entries), |
| | | kind: kind |
| | | }); |
| | | }, 'Iterator', function next() { |
| | | var state = getInternalIteratorState(this); |
| | | var kind = state.kind; |
| | | var step = state.iterator.next(); |
| | | var entry = step.value; |
| | | if (!step.done) { |
| | | step.value = kind === 'keys' ? entry.key : kind === 'values' ? entry.value : [entry.key, entry.value]; |
| | | } return step; |
| | | }); |
| | | |
| | | // `URLSearchParams` constructor |
| | | // https://url.spec.whatwg.org/#interface-urlsearchparams |
| | | var URLSearchParamsConstructor = function URLSearchParams(/* init */) { |
| | | anInstance(this, URLSearchParamsConstructor, URL_SEARCH_PARAMS); |
| | | var init = arguments.length > 0 ? arguments[0] : undefined; |
| | | var that = this; |
| | | var entries = []; |
| | | var iteratorMethod, iterator, next, step, entryIterator, entryNext, first, second, key; |
| | | |
| | | setInternalState(that, { |
| | | type: URL_SEARCH_PARAMS, |
| | | entries: entries, |
| | | updateURL: function () { /* empty */ }, |
| | | updateSearchParams: updateSearchParams |
| | | }); |
| | | |
| | | if (init !== undefined) { |
| | | if (isObject(init)) { |
| | | iteratorMethod = getIteratorMethod(init); |
| | | if (iteratorMethod) { |
| | | iterator = getIterator(init, iteratorMethod); |
| | | next = iterator.next; |
| | | while (!(step = next.call(iterator)).done) { |
| | | entryIterator = getIterator(anObject(step.value)); |
| | | entryNext = entryIterator.next; |
| | | if ( |
| | | (first = entryNext.call(entryIterator)).done || |
| | | (second = entryNext.call(entryIterator)).done || |
| | | !entryNext.call(entryIterator).done |
| | | ) throw TypeError('Expected sequence with length 2'); |
| | | entries.push({ key: $toString(first.value), value: $toString(second.value) }); |
| | | } |
| | | } else for (key in init) if (hasOwn(init, key)) entries.push({ key: key, value: $toString(init[key]) }); |
| | | } else { |
| | | parseSearchParams( |
| | | entries, |
| | | typeof init === 'string' ? init.charAt(0) === '?' ? init.slice(1) : init : $toString(init) |
| | | ); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype; |
| | | |
| | | redefineAll(URLSearchParamsPrototype, { |
| | | // `URLSearchParams.prototype.append` method |
| | | // https://url.spec.whatwg.org/#dom-urlsearchparams-append |
| | | append: function append(name, value) { |
| | | validateArgumentsLength(arguments.length, 2); |
| | | var state = getInternalParamsState(this); |
| | | state.entries.push({ key: $toString(name), value: $toString(value) }); |
| | | state.updateURL(); |
| | | }, |
| | | // `URLSearchParams.prototype.delete` method |
| | | // https://url.spec.whatwg.org/#dom-urlsearchparams-delete |
| | | 'delete': function (name) { |
| | | validateArgumentsLength(arguments.length, 1); |
| | | var state = getInternalParamsState(this); |
| | | var entries = state.entries; |
| | | var key = $toString(name); |
| | | var index = 0; |
| | | while (index < entries.length) { |
| | | if (entries[index].key === key) entries.splice(index, 1); |
| | | else index++; |
| | | } |
| | | state.updateURL(); |
| | | }, |
| | | // `URLSearchParams.prototype.get` method |
| | | // https://url.spec.whatwg.org/#dom-urlsearchparams-get |
| | | get: function get(name) { |
| | | validateArgumentsLength(arguments.length, 1); |
| | | var entries = getInternalParamsState(this).entries; |
| | | var key = $toString(name); |
| | | var index = 0; |
| | | for (; index < entries.length; index++) { |
| | | if (entries[index].key === key) return entries[index].value; |
| | | } |
| | | return null; |
| | | }, |
| | | // `URLSearchParams.prototype.getAll` method |
| | | // https://url.spec.whatwg.org/#dom-urlsearchparams-getall |
| | | getAll: function getAll(name) { |
| | | validateArgumentsLength(arguments.length, 1); |
| | | var entries = getInternalParamsState(this).entries; |
| | | var key = $toString(name); |
| | | var result = []; |
| | | var index = 0; |
| | | for (; index < entries.length; index++) { |
| | | if (entries[index].key === key) result.push(entries[index].value); |
| | | } |
| | | return result; |
| | | }, |
| | | // `URLSearchParams.prototype.has` method |
| | | // https://url.spec.whatwg.org/#dom-urlsearchparams-has |
| | | has: function has(name) { |
| | | validateArgumentsLength(arguments.length, 1); |
| | | var entries = getInternalParamsState(this).entries; |
| | | var key = $toString(name); |
| | | var index = 0; |
| | | while (index < entries.length) { |
| | | if (entries[index++].key === key) return true; |
| | | } |
| | | return false; |
| | | }, |
| | | // `URLSearchParams.prototype.set` method |
| | | // https://url.spec.whatwg.org/#dom-urlsearchparams-set |
| | | set: function set(name, value) { |
| | | validateArgumentsLength(arguments.length, 1); |
| | | var state = getInternalParamsState(this); |
| | | var entries = state.entries; |
| | | var found = false; |
| | | var key = $toString(name); |
| | | var val = $toString(value); |
| | | var index = 0; |
| | | var entry; |
| | | for (; index < entries.length; index++) { |
| | | entry = entries[index]; |
| | | if (entry.key === key) { |
| | | if (found) entries.splice(index--, 1); |
| | | else { |
| | | found = true; |
| | | entry.value = val; |
| | | } |
| | | } |
| | | } |
| | | if (!found) entries.push({ key: key, value: val }); |
| | | state.updateURL(); |
| | | }, |
| | | // `URLSearchParams.prototype.sort` method |
| | | // https://url.spec.whatwg.org/#dom-urlsearchparams-sort |
| | | sort: function sort() { |
| | | var state = getInternalParamsState(this); |
| | | var entries = state.entries; |
| | | // Array#sort is not stable in some engines |
| | | var slice = entries.slice(); |
| | | var entry, entriesIndex, sliceIndex; |
| | | entries.length = 0; |
| | | for (sliceIndex = 0; sliceIndex < slice.length; sliceIndex++) { |
| | | entry = slice[sliceIndex]; |
| | | for (entriesIndex = 0; entriesIndex < sliceIndex; entriesIndex++) { |
| | | if (entries[entriesIndex].key > entry.key) { |
| | | entries.splice(entriesIndex, 0, entry); |
| | | break; |
| | | } |
| | | } |
| | | if (entriesIndex === sliceIndex) entries.push(entry); |
| | | } |
| | | state.updateURL(); |
| | | }, |
| | | // `URLSearchParams.prototype.forEach` method |
| | | forEach: function forEach(callback /* , thisArg */) { |
| | | var entries = getInternalParamsState(this).entries; |
| | | var boundFunction = bind(callback, arguments.length > 1 ? arguments[1] : undefined, 3); |
| | | var index = 0; |
| | | var entry; |
| | | while (index < entries.length) { |
| | | entry = entries[index++]; |
| | | boundFunction(entry.value, entry.key, this); |
| | | } |
| | | }, |
| | | // `URLSearchParams.prototype.keys` method |
| | | keys: function keys() { |
| | | return new URLSearchParamsIterator(this, 'keys'); |
| | | }, |
| | | // `URLSearchParams.prototype.values` method |
| | | values: function values() { |
| | | return new URLSearchParamsIterator(this, 'values'); |
| | | }, |
| | | // `URLSearchParams.prototype.entries` method |
| | | entries: function entries() { |
| | | return new URLSearchParamsIterator(this, 'entries'); |
| | | } |
| | | }, { enumerable: true }); |
| | | |
| | | // `URLSearchParams.prototype[@@iterator]` method |
| | | redefine(URLSearchParamsPrototype, ITERATOR, URLSearchParamsPrototype.entries, { name: 'entries' }); |
| | | |
| | | // `URLSearchParams.prototype.toString` method |
| | | // https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior |
| | | redefine(URLSearchParamsPrototype, 'toString', function toString() { |
| | | var entries = getInternalParamsState(this).entries; |
| | | var result = []; |
| | | var index = 0; |
| | | var entry; |
| | | while (index < entries.length) { |
| | | entry = entries[index++]; |
| | | result.push(serialize(entry.key) + '=' + serialize(entry.value)); |
| | | } return result.join('&'); |
| | | }, { enumerable: true }); |
| | | |
| | | setToStringTag(URLSearchParamsConstructor, URL_SEARCH_PARAMS); |
| | | |
| | | $({ global: true, forced: !USE_NATIVE_URL }, { |
| | | URLSearchParams: URLSearchParamsConstructor |
| | | }); |
| | | |
| | | // Wrap `fetch` and `Request` for correct work with polyfilled `URLSearchParams` |
| | | if (!USE_NATIVE_URL && isCallable(Headers)) { |
| | | var wrapRequestOptions = function (init) { |
| | | if (isObject(init)) { |
| | | var body = init.body; |
| | | var headers; |
| | | if (classof(body) === URL_SEARCH_PARAMS) { |
| | | headers = init.headers ? new Headers(init.headers) : new Headers(); |
| | | if (!headers.has('content-type')) { |
| | | headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8'); |
| | | } |
| | | return create(init, { |
| | | body: createPropertyDescriptor(0, String(body)), |
| | | headers: createPropertyDescriptor(0, headers) |
| | | }); |
| | | } |
| | | } return init; |
| | | }; |
| | | |
| | | if (isCallable(nativeFetch)) { |
| | | $({ global: true, enumerable: true, forced: true }, { |
| | | fetch: function fetch(input /* , init */) { |
| | | return nativeFetch(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {}); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | if (isCallable(NativeRequest)) { |
| | | var RequestConstructor = function Request(input /* , init */) { |
| | | anInstance(this, RequestConstructor, 'Request'); |
| | | return new NativeRequest(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {}); |
| | | }; |
| | | |
| | | RequestPrototype.constructor = RequestConstructor; |
| | | RequestConstructor.prototype = RequestPrototype; |
| | | |
| | | $({ global: true, forced: true }, { |
| | | Request: RequestConstructor |
| | | }); |
| | | } |
| | | } |
| | | |
| | | module.exports = { |
| | | URLSearchParams: URLSearchParamsConstructor, |
| | | getState: getInternalParamsState |
| | | }; |
| | | // TODO: Remove this module from `core-js@4` since it's replaced to module below |
| | | require('../modules/web.url-search-params.constructor'); |