summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/js/tests/url_search_params_test.ts30
-rw-r--r--cli/js/web/url_search_params.ts90
2 files changed, 75 insertions, 45 deletions
diff --git a/cli/js/tests/url_search_params_test.ts b/cli/js/tests/url_search_params_test.ts
index 3e71d2900..7b7dbab76 100644
--- a/cli/js/tests/url_search_params_test.ts
+++ b/cli/js/tests/url_search_params_test.ts
@@ -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);
+});
diff --git a/cli/js/web/url_search_params.ts b/cli/js/web/url_search_params.ts
index 221a70ab1..35439b0e2 100644
--- a/cli/js/web/url_search_params.ts
+++ b/cli/js/web/url_search_params.ts
@@ -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);
}
}