From 45025beb78c059f97e9997e7a57c07ea22ef2dbb Mon Sep 17 00:00:00 2001 From: godzylinux Date: Wed, 22 May 2024 13:21:01 +0330 Subject: [PATCH] fixed where updating the search wouldn't keep the new order of how they are added --- .../src/reactivity/url-search-params.js | 13 +++--- .../src/reactivity/url-search-params.test.ts | 36 +++++++++++++++ packages/svelte/src/reactivity/url.js | 44 ++++++++++++++----- packages/svelte/src/reactivity/url.test.ts | 1 - 4 files changed, 77 insertions(+), 17 deletions(-) diff --git a/packages/svelte/src/reactivity/url-search-params.js b/packages/svelte/src/reactivity/url-search-params.js index 0a55c0b249..3def2c7acd 100644 --- a/packages/svelte/src/reactivity/url-search-params.js +++ b/packages/svelte/src/reactivity/url-search-params.js @@ -2,27 +2,28 @@ import { make_reactive } from './utils.js'; export const ReactiveURLSearchParams = make_reactive(URLSearchParams, { write_properties: ['append', 'delete', 'set', 'sort'], - read_properties: ['get', 'has'], + read_properties: ['get', 'has', 'getAll'], interceptors: { set: (notify_read_properties, value, property, ...params) => { if (typeof params[0] == 'string' && value.get(params[0]) === params[1]) { return false; } - notify_read_properties(['get', 'has'], params[0]); + notify_read_properties(['get', 'has', 'getAll'], params[0]); return true; }, append: (notify_read_properties, value, property, ...params) => { - if (typeof params[0] == 'string' && value.get(params[0]) === params[1]) { - return false; + notify_read_properties(['getAll'], params[0]); + + if (typeof params[0] == 'string' && !value.has(params[0])) { + notify_read_properties(['get', 'has'], params[0]); } - notify_read_properties(['get', 'has'], params[0]); return true; }, delete: (notify_read_properties, value, property, ...params) => { if (typeof params[0] == 'string' && !value.has(params[0])) { return false; } - notify_read_properties(['get', 'has'], params[0]); + notify_read_properties(['get', 'has', 'getAll'], params[0]); return true; } } diff --git a/packages/svelte/src/reactivity/url-search-params.test.ts b/packages/svelte/src/reactivity/url-search-params.test.ts index 0e60106a7b..d93b4b964e 100644 --- a/packages/svelte/src/reactivity/url-search-params.test.ts +++ b/packages/svelte/src/reactivity/url-search-params.test.ts @@ -113,3 +113,39 @@ test('URLSearchParams.get', () => { cleanup(); }); + +test('URLSearchParams.getAll', () => { + const params = new ReactiveURLSearchParams('a=b&c=d'); + const log: any = []; + + const cleanup = effect_root(() => { + render_effect(() => { + log.push(params.get('a')); + }); + render_effect(() => { + log.push(params.get('c')); + }); + render_effect(() => { + log.push(params.get('q')); + }); + render_effect(() => { + log.push(params.getAll('a')); + }); + render_effect(() => { + log.push(params.getAll('q')); + }); + }); + + flushSync(() => { + // this shouldn't affect params.get(a) because it already exists + params.append('a', 'b1'); + }); + + flushSync(() => { + params.append('q', 'z'); + }); + + assert.deepEqual(log, ['b', 'd', null, ['b'], [], ['b', 'b1'], 'z', ['z']]); + + cleanup(); +}); diff --git a/packages/svelte/src/reactivity/url.js b/packages/svelte/src/reactivity/url.js index 86afe23760..d2b2b517f8 100644 --- a/packages/svelte/src/reactivity/url.js +++ b/packages/svelte/src/reactivity/url.js @@ -1,3 +1,4 @@ +import { untrack } from '../index-client.js'; import { ReactiveURLSearchParams } from './url-search-params.js'; import { make_reactive } from './utils.js'; @@ -71,21 +72,44 @@ class URLWithReactiveSearchParams extends URL { } if (url_updated) { - Array.from(this.searchParams.keys()).forEach((key) => { - // remove keys that don't exist anymore - if (!super.searchParams.has(key)) { - this.searchParams.delete(key); - } - }); - for (const key of super.searchParams.keys()) { - // set/update keys - this.searchParams.set(key, /** @type {string} */ (super.searchParams.get(key))); - } + this.#update_search_params_from_url(); } else if (search_params_updated) { + // updating url from params this.search = this.searchParams.toString(); } } + #update_search_params_from_url() { + /** + * keeping track of this is required because we have to keep the order in which they are updated + * @type {string[]} + */ + const keys_with_no_change = []; + + // remove keys that don't exist anymore and notify others + for (const [key, value] of Array.from(this.searchParams.entries())) { + if (!super.searchParams.has(key) || value == super.searchParams.get(key)) { + keys_with_no_change.push(key); + untrack(() => { + this.searchParams.delete(key); + }); + continue; + } + this.searchParams.delete(key); + } + + // set or update keys based on the params + for (const [key, value] of super.searchParams.entries()) { + if (keys_with_no_change.includes(key)) { + untrack(() => { + this.searchParams.set(key, value); + }); + continue; + } + this.searchParams.set(key, value); + } + } + /** * @override */ diff --git a/packages/svelte/src/reactivity/url.test.ts b/packages/svelte/src/reactivity/url.test.ts index aa662047a5..da88358f8c 100644 --- a/packages/svelte/src/reactivity/url.test.ts +++ b/packages/svelte/src/reactivity/url.test.ts @@ -67,7 +67,6 @@ test('url.searchParams', () => { 'foo: baz', 'q: true', 'search: ?q=kit&foo=baz&foo=qux', - 'foo: baz', 'search: ?q=kit', 'foo: null' ]);