diff --git a/js/url_search_params.ts b/js/url_search_params.ts index 85f4c0619f..666ba69515 100644 --- a/js/url_search_params.ts +++ b/js/url_search_params.ts @@ -1,6 +1,6 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. import { URL } from "./url"; -import { requiredArguments } from "./util"; +import { requiredArguments, isIterable } from "./util"; export class URLSearchParams { private params: Array<[string, string]> = []; @@ -17,6 +17,11 @@ export class URLSearchParams { return; } + if (isIterable(init)) { + this.params = [...init]; + return; + } + if (Object(init) !== init) { return; } diff --git a/js/url_search_params_test.ts b/js/url_search_params_test.ts index d37b554975..e270dd7ff6 100644 --- a/js/url_search_params_test.ts +++ b/js/url_search_params_test.ts @@ -217,3 +217,13 @@ test(function urlSearchParamsDeletingAppendedMultiple(): void { params.delete("first"); assertEquals(params.has("first"), false); }); + +// ref: https://github.com/web-platform-tests/wpt/blob/master/url/urlsearchparams-constructor.any.js#L176-L182 +test(function urlSearchParamsCustomSymbolIterator(): void { + const params = new URLSearchParams(); + params[Symbol.iterator] = function*(): IterableIterator<[string, string]> { + yield ["a", "b"]; + }; + const params1 = new URLSearchParams((params as unknown) as string[][]); + assertEquals(params1.get("a"), "b"); +}); diff --git a/js/util.ts b/js/util.ts index a035d761ae..da56465a2c 100644 --- a/js/util.ts +++ b/js/util.ts @@ -122,6 +122,19 @@ export function isObject(o: unknown): o is object { return o != null && typeof o === "object"; } +// Returns whether o is iterable. +export function isIterable( + o: T +): o is T & Iterable<[P, K]> { + // checks for null and undefined + if (o == null) { + return false; + } + return ( + typeof ((o as unknown) as Iterable<[P, K]>)[Symbol.iterator] === "function" + ); +} + // @internal export function requiredArguments( name: string,