1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 23:34:47 -05:00

fix(#2142) make URLSearchParams more standardized (#4695)

This commit is contained in:
Fenzland 2020-04-23 22:30:32 +08:00 committed by GitHub
parent 65bba2b87e
commit cb935a375c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 45 deletions

View file

@ -243,3 +243,33 @@ unitTest(
assertEquals(params1.get("1"), "2");
}
);
// If a class extends URLSearchParams, override one method should not change another's behavior.
unitTest(
function urlSearchParamsOverridingAppendNotChangeConstructorAndSet(): void {
let overridedAppendCalled = 0;
class CustomSearchParams extends URLSearchParams {
append(name: string, value: string): void {
++overridedAppendCalled;
super.append(name, value);
}
}
new CustomSearchParams("foo=bar");
new CustomSearchParams([["foo", "bar"]]);
new CustomSearchParams(new CustomSearchParams({ foo: "bar" }));
new CustomSearchParams().set("foo", "bar");
assertEquals(overridedAppendCalled, 0);
}
);
unitTest(function urlSearchParamsOverridingEntriesNotChangeForEach(): void {
class CustomSearchParams extends URLSearchParams {
*entries(): IterableIterator<[string, string]> {
yield* [];
}
}
let loopCount = 0;
const params = new CustomSearchParams({ foo: "bar" });
params.forEach(() => void ++loopCount);
assertEquals(loopCount, 1);
});

View file

@ -5,10 +5,38 @@ import { isIterable, requiredArguments } from "./util.ts";
/** @internal */
export const urls = new WeakMap<URLSearchParams, URL | null>();
function handleStringInitialization(
searchParams: URLSearchParams,
init: string
): void {
export class URLSearchParamsImpl implements URLSearchParams {
#params: Array<[string, string]> = [];
constructor(init: string | string[][] | Record<string, string> = "") {
if (typeof init === "string") {
this.#handleStringInitialization(init);
return;
}
if (Array.isArray(init) || isIterable(init)) {
this.#handleArrayInitialization(init);
return;
}
if (Object(init) !== init) {
return;
}
if (init instanceof URLSearchParamsImpl) {
this.#params = [...init.#params];
return;
}
// Overload: record<USVString, USVString>
for (const key of Object.keys(init)) {
this.#append(key, init[key]);
}
urls.set(this, null);
}
#handleStringInitialization = (init: string): void => {
// Overload: USVString
// If init is a string and starts with U+003F (?),
// remove the first code point from init.
@ -24,14 +52,13 @@ function handleStringInitialization(
const position = pair.indexOf("=");
const name = pair.slice(0, position === -1 ? pair.length : position);
const value = pair.slice(name.length + 1);
searchParams.append(decodeURIComponent(name), decodeURIComponent(value));
this.#append(decodeURIComponent(name), decodeURIComponent(value));
}
}
};
function handleArrayInitialization(
searchParams: URLSearchParams,
#handleArrayInitialization = (
init: string[][] | Iterable<[string, string]>
): void {
): void => {
// Overload: sequence<sequence<USVString>>
for (const tuple of init) {
// If pair does not contain exactly two items, then throw a TypeError.
@ -40,40 +67,9 @@ function handleArrayInitialization(
"URLSearchParams.constructor tuple array argument must only contain pair elements"
);
}
searchParams.append(tuple[0], tuple[1]);
}
}
export class URLSearchParamsImpl implements URLSearchParams {
#params: Array<[string, string]> = [];
constructor(init: string | string[][] | Record<string, string> = "") {
if (typeof init === "string") {
handleStringInitialization(this, init);
return;
}
if (Array.isArray(init) || isIterable(init)) {
handleArrayInitialization(this, init);
return;
}
if (Object(init) !== init) {
return;
}
if (init instanceof URLSearchParamsImpl) {
this.#params = [...init.#params];
return;
}
// Overload: record<USVString, USVString>
for (const key of Object.keys(init)) {
this.append(key, init[key]);
}
urls.set(this, null);
this.#append(tuple[0], tuple[1]);
}
};
#updateSteps = (): void => {
const url = urls.get(this);
@ -89,9 +85,13 @@ export class URLSearchParamsImpl implements URLSearchParams {
parts.get(url)!.query = query;
};
#append = (name: string, value: string): void => {
this.#params.push([String(name), String(value)]);
};
append(name: string, value: string): void {
requiredArguments("URLSearchParams.append", arguments.length, 2);
this.#params.push([String(name), String(value)]);
this.#append(name, value);
this.#updateSteps();
}
@ -167,7 +167,7 @@ export class URLSearchParamsImpl implements URLSearchParams {
// Otherwise, append a new name-value pair whose name is name
// and value is value, to list.
if (!found) {
this.append(name, value);
this.#append(name, value);
}
this.#updateSteps();
@ -189,7 +189,7 @@ export class URLSearchParamsImpl implements URLSearchParams {
callbackfn = callbackfn.bind(thisArg);
}
for (const [key, value] of this.entries()) {
for (const [key, value] of this.#params) {
callbackfn(value, key, this);
}
}