From 3dbd18af0950400eed7063bef7cb1f7ff27c4a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BF=B7=E6=B8=A1?= Date: Wed, 19 Dec 2018 09:14:59 +0800 Subject: [PATCH] Fix URLSearchParams set() and constructor() (#1368) --- js/url_search_params.ts | 31 +++++++++++++++++++++++++++++-- js/url_search_params_test.ts | 30 ++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/js/url_search_params.ts b/js/url_search_params.ts index 228c369560..06369ae29d 100644 --- a/js/url_search_params.ts +++ b/js/url_search_params.ts @@ -24,6 +24,12 @@ export class URLSearchParams { } else if (Array.isArray(init)) { // Overload: sequence> for (const tuple of init) { + // If pair does not contain exactly two items, then throw a TypeError. + if (tuple.length !== 2) { + const errMsg = + "Each query pair must be an iterable [name, value] tuple"; + throw new TypeError(errMsg); + } this.append(tuple[0], tuple[1]); } } else if (Object(init) === init) { @@ -106,8 +112,29 @@ export class URLSearchParams { * searchParams.set('name', 'value'); */ set(name: string, value: string): void { - this.delete(name); - this.append(name, value); + // If there are any name-value pairs whose name is name, in list, + // set the value of the first such name-value pair to value + // and remove the others. + let found = false; + let i = 0; + while (i < this.params.length) { + if (this.params[i][0] === name) { + if (!found) { + this.params[i][1] = value; + found = true; + } else { + this.params.splice(i, 1); + continue; + } + } + i++; + } + + // Otherwise, append a new name-value pair whose name is name + // and value is value, to list. + if (!found) { + this.append(name, value); + } } /** Sort all key/value pairs contained in this object in place and diff --git a/js/url_search_params_test.ts b/js/url_search_params_test.ts index 46e8103d93..802ab288b1 100644 --- a/js/url_search_params_test.ts +++ b/js/url_search_params_test.ts @@ -59,11 +59,18 @@ test(function urlSearchParamsHasSuccess() { assert(!searchParams.has("c")); }); -test(function urlSearchParamsSetSuccess() { +test(function urlSearchParamsSetReplaceFirstAndRemoveOthers() { const init = "a=54&b=true&a=true"; const searchParams = new URLSearchParams(init); searchParams.set("a", "false"); - assertEqual(searchParams.toString(), "b=true&a=false"); + assertEqual(searchParams.toString(), "a=false&b=true"); +}); + +test(function urlSearchParamsSetAppendNew() { + const init = "a=54&b=true&a=true"; + const searchParams = new URLSearchParams(init); + searchParams.set("c", "foo"); + assertEqual(searchParams.toString(), "a=54&b=true&a=true&c=foo"); }); test(function urlSearchParamsSortSuccess() { @@ -112,3 +119,22 @@ test(function urlSearchParamsMissingPair() { const searchParams = new URLSearchParams(init); assertEqual(searchParams.toString(), "c=4&a=54"); }); + +// If pair does not contain exactly two items, then throw a TypeError. +// ref https://url.spec.whatwg.org/#interface-urlsearchparams +test(function urlSearchParamsShouldThrowTypeError() { + let hasThrown = 0; + + try { + new URLSearchParams([["1"]]); + hasThrown = 1; + } catch (err) { + if (err instanceof TypeError) { + hasThrown = 2; + } else { + hasThrown = 3; + } + } + + assertEqual(hasThrown, 2); +});