react-native
Version:
A framework for building native apps using React
146 lines (126 loc) • 3.94 kB
JavaScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/
// Small subset from whatwg-url: https://github.com/jsdom/whatwg-url/tree/master/src
// The reference code bloat comes from Unicode issues with URLs, so those won't work here.
export class URLSearchParams {
_searchParams: Map<string, string[]> = new Map();
constructor(params?: Record<string, string> | string | [string, string][]) {
if (params === null) {
return;
}
if (typeof params === 'string') {
// URLSearchParams("key1=value1&key2=value2");
params
.replace(/^\?/, '')
.split('&')
.forEach(pair => {
if (!pair) {
return;
}
const [key, value] = pair
.split('=')
.map(part => decodeURIComponent(part.replace(/\+/g, ' ')));
this.append(key, value);
});
} else if (Array.isArray(params)) {
//URLSearchParams([["key1", "value1"], ["key2", "value2"]]);
params.forEach(([key, value]) => this.append(key, value));
} else if (typeof params === 'object') {
//URLSearchParams({ key1: "value1", key2: "value2" });
Object.entries(params).forEach(([key, value]) => this.append(key, value));
}
}
append(key: string, value: string): void {
if (!this._searchParams.has(key)) {
this._searchParams.set(key, [value]); // Initialize with an array if key is missing
} else {
this._searchParams.get(key)?.push(value); // Else push the value to the array
}
}
delete(name: string): void {
this._searchParams.delete(name);
}
get(name: string): string | null {
const values = this._searchParams.get(name);
return values ? values[0] : null;
}
getAll(name: string): string[] {
return this._searchParams.get(name) ?? [];
}
has(name: string): boolean {
return this._searchParams.has(name);
}
set(name: string, value: string): void {
this._searchParams.set(name, [value]);
}
keys(): Iterator<string> {
return this._searchParams.keys();
}
values(): Iterator<string> {
function* generateValues(params: Map<string, string[]>): Iterator<string> {
for (const valueArray of params.values()) {
for (const value of valueArray) {
yield value;
}
}
}
return generateValues(this._searchParams);
}
entries(): Iterator<[string, string]> {
function* generateEntries(
params: Map<string, string[]>,
): Iterator<[string, string]> {
for (const [key, values] of params) {
for (const value of values) {
yield [key, value];
}
}
}
return generateEntries(this._searchParams);
}
forEach(
callback: (value: string, key: string, searchParams: this) => void,
): void {
for (const [key, values] of this._searchParams) {
for (const value of values) {
callback(value, key, this);
}
}
}
sort(): void {
this._searchParams = new Map(
[...this._searchParams.entries()].sort(([a], [b]) => a.localeCompare(b)),
);
}
// $FlowFixMe[unsupported-syntax]
[Symbol.iterator](): Iterator<[string, string]> {
const entries: [string, string][] = [];
for (const [key, values] of this._searchParams) {
for (const value of values) {
entries.push([key, value]);
}
}
return entries[Symbol.iterator]();
}
toString(): string {
return Array.from(this._searchParams.entries())
.map(([key, values]) =>
values
.map(
value =>
`${encodeURIComponent(key).replace(/%20/g, '+')}=${encodeURIComponent(
value,
).replace(/%20/g, '+')}`, // Convert only spaces to '+'
)
.join('&'),
)
.join('&');
}
}