fixed where updating the search wouldn't keep the new order of how they are added

pull/11774/head
godzylinux 2 years ago
parent 850d285e40
commit 852205144b

@ -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;
}
}

@ -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();
});

@ -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
*/

@ -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'
]);

Loading…
Cancel
Save