mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
parent
65bba2b87e
commit
cb935a375c
2 changed files with 75 additions and 45 deletions
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -5,56 +5,17 @@ import { isIterable, requiredArguments } from "./util.ts";
|
|||
/** @internal */
|
||||
export const urls = new WeakMap<URLSearchParams, URL | null>();
|
||||
|
||||
function handleStringInitialization(
|
||||
searchParams: URLSearchParams,
|
||||
init: string
|
||||
): void {
|
||||
// Overload: USVString
|
||||
// If init is a string and starts with U+003F (?),
|
||||
// remove the first code point from init.
|
||||
if (init.charCodeAt(0) === 0x003f) {
|
||||
init = init.slice(1);
|
||||
}
|
||||
|
||||
for (const pair of init.split("&")) {
|
||||
// Empty params are ignored
|
||||
if (pair.length === 0) {
|
||||
continue;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
function handleArrayInitialization(
|
||||
searchParams: URLSearchParams,
|
||||
init: string[][] | Iterable<[string, string]>
|
||||
): void {
|
||||
// Overload: sequence<sequence<USVString>>
|
||||
for (const tuple of init) {
|
||||
// If pair does not contain exactly two items, then throw a TypeError.
|
||||
if (tuple.length !== 2) {
|
||||
throw new TypeError(
|
||||
"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);
|
||||
this.#handleStringInitialization(init);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(init) || isIterable(init)) {
|
||||
handleArrayInitialization(this, init);
|
||||
this.#handleArrayInitialization(init);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -69,12 +30,47 @@ export class URLSearchParamsImpl implements URLSearchParams {
|
|||
|
||||
// Overload: record<USVString, USVString>
|
||||
for (const key of Object.keys(init)) {
|
||||
this.append(key, init[key]);
|
||||
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.
|
||||
if (init.charCodeAt(0) === 0x003f) {
|
||||
init = init.slice(1);
|
||||
}
|
||||
|
||||
for (const pair of init.split("&")) {
|
||||
// Empty params are ignored
|
||||
if (pair.length === 0) {
|
||||
continue;
|
||||
}
|
||||
const position = pair.indexOf("=");
|
||||
const name = pair.slice(0, position === -1 ? pair.length : position);
|
||||
const value = pair.slice(name.length + 1);
|
||||
this.#append(decodeURIComponent(name), decodeURIComponent(value));
|
||||
}
|
||||
};
|
||||
|
||||
#handleArrayInitialization = (
|
||||
init: string[][] | Iterable<[string, string]>
|
||||
): void => {
|
||||
// Overload: sequence<sequence<USVString>>
|
||||
for (const tuple of init) {
|
||||
// If pair does not contain exactly two items, then throw a TypeError.
|
||||
if (tuple.length !== 2) {
|
||||
throw new TypeError(
|
||||
"URLSearchParams.constructor tuple array argument must only contain pair elements"
|
||||
);
|
||||
}
|
||||
this.#append(tuple[0], tuple[1]);
|
||||
}
|
||||
};
|
||||
|
||||
#updateSteps = (): void => {
|
||||
const url = urls.get(this);
|
||||
if (url == null) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue