From b344a7f81fa00d1611212cac82b631f9d1dffdf0 Mon Sep 17 00:00:00 2001 From: Prabhanjan <24642451+Sparkenstein@users.noreply.github.com> Date: Wed, 12 Aug 2020 15:38:24 +0530 Subject: [PATCH] fix: URLSearchParams.toString() behaviour is different from browsers (#7017) --- cli/rt/11_url.js | 12 +++++++- cli/tests/unit/url_search_params_test.ts | 38 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/cli/rt/11_url.js b/cli/rt/11_url.js index 202d35e814..cb42e22c73 100644 --- a/cli/rt/11_url.js +++ b/cli/rt/11_url.js @@ -222,7 +222,7 @@ return this.#params .map( (tuple) => - `${encodeURIComponent(tuple[0])}=${encodeURIComponent(tuple[1])}`, + `${encodeSearchParam(tuple[0])}=${encodeSearchParam(tuple[1])}`, ) .join("&"); } @@ -792,6 +792,11 @@ return ["\u0000", "\u0009", "\u000A", "\u000D", "\u0020", "\u0023", "\u0025", "\u002F", "\u003A", "\u003C", "\u003E", "\u003F", "\u0040", "\u005B", "\u005C", "\u005D", "\u005E"].includes(c); } + function charInFormUrlencodedSet(c) { + // deno-fmt-ignore + return charInUserinfoSet(c) || ["\u0021", "\u0024", "\u0025", "\u0026", "\u0027", "\u0028", "\u0029", "\u002B", "\u002C", "\u007E"].includes(c); + } + const encoder = new TextEncoder(); function encodeChar(c) { @@ -876,6 +881,11 @@ ); } + function encodeSearchParam(s) { + return [...s].map((c) => (charInFormUrlencodedSet(c) ? encodeChar(c) : c)) + .join("").replace("%20", "+"); + } + window.__bootstrap.url = { URL, URLSearchParams, diff --git a/cli/tests/unit/url_search_params_test.ts b/cli/tests/unit/url_search_params_test.ts index 6965fe1288..7698ef1ce6 100644 --- a/cli/tests/unit/url_search_params_test.ts +++ b/cli/tests/unit/url_search_params_test.ts @@ -1,6 +1,44 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. import { unitTest, assert, assertEquals } from "./test_util.ts"; +unitTest(function urlSearchParamsWithSpace(): void { + const init = { str: "hello world" }; + const searchParams = new URLSearchParams(init).toString(); + assertEquals(searchParams, "str=hello+world"); +}); + +unitTest(function urlSearchParamsWithExclamation(): void { + const init = [ + ["str", "hello, world!"], + ]; + const searchParams = new URLSearchParams(init).toString(); + assertEquals(searchParams, "str=hello%2C+world%21"); +}); + +unitTest(function urlSearchParamsWithQuotes(): void { + const init = [ + ["str", "'hello world'"], + ]; + const searchParams = new URLSearchParams(init).toString(); + assertEquals(searchParams, "str=%27hello+world%27"); +}); + +unitTest(function urlSearchParamsWithBraket(): void { + const init = [ + ["str", "(hello world)"], + ]; + const searchParams = new URLSearchParams(init).toString(); + assertEquals(searchParams, "str=%28hello+world%29"); +}); + +unitTest(function urlSearchParamsWithTilde(): void { + const init = [ + ["str", "hello~world"], + ]; + const searchParams = new URLSearchParams(init).toString(); + assertEquals(searchParams, "str=hello%7Eworld"); +}); + unitTest(function urlSearchParamsInitString(): void { const init = "c=4&a=2&b=3&%C3%A1=1"; const searchParams = new URLSearchParams(init);