remove a bit of indirection

pull/12285/head
Rich Harris 2 years ago
parent fb1514b12e
commit 8d23abdd22

@ -1,21 +1,28 @@
import { source } from '../internal/client/reactivity/sources.js';
import { get } from '../internal/client/runtime.js';
import { get_current_url } from './url.js';
import { increment } from './utils.js';
export const REPLACE = Symbol();
export const onChange = Symbol();
export class SvelteURLSearchParams extends URLSearchParams {
#version = source(0);
/**
* @type {((command: "set" | "append" | "delete" | "sort", ...args: any[])=>void ) | null}
*/
[onChange] = null;
#url = get_current_url();
#updating = false;
#update_url() {
if (!this.#url || this.#updating) return;
const search = this.toString();
this.#url.search = search && `?${search}`;
}
/**
* @param {URLSearchParams} params
*/
[REPLACE](params) {
this.#updating = true;
for (const key of [...super.keys()]) {
super.delete(key);
}
@ -25,6 +32,8 @@ export class SvelteURLSearchParams extends URLSearchParams {
}
increment(this.#version);
this.#updating = false;
}
/**
@ -33,10 +42,9 @@ export class SvelteURLSearchParams extends URLSearchParams {
* @returns {void}
*/
append(name, value) {
var res = super.append(name, value);
this[onChange]?.('append', name, value);
super.append(name, value);
this.#update_url();
increment(this.#version);
return res;
}
/**
@ -46,12 +54,11 @@ export class SvelteURLSearchParams extends URLSearchParams {
*/
delete(name, value) {
var has_value = super.has(name, value);
var res = super.delete(name, value);
super.delete(name, value);
if (has_value) {
this[onChange]?.('delete', name, value);
this.#update_url();
increment(this.#version);
}
return res;
}
/**
@ -93,21 +100,20 @@ export class SvelteURLSearchParams extends URLSearchParams {
* @returns {void}
*/
set(name, value) {
var value_before_change = super.getAll(name).join('');
var previous = super.getAll(name).join('');
super.set(name, value);
// can't use has(name, value), because for something like https://svelte.dev?foo=1&bar=2&foo=3
// if you set `foo` to 1, then foo=3 gets deleted whilst `has("foo", "1")` returns true
if (value_before_change !== super.getAll(name).join('')) {
this[onChange]?.('set', name, value);
if (previous !== super.getAll(name).join('')) {
this.#update_url();
increment(this.#version);
}
}
sort() {
var res = super.sort();
this[onChange]?.('sort');
super.sort();
this.#update_url();
increment(this.#version);
return res;
}
toString() {

@ -3,6 +3,30 @@ import { flushSync } from '../index-client.js';
import { assert, test } from 'vitest';
import { SvelteURLSearchParams } from './url-search-params';
test('new URLSearchParams', () => {
const params = new SvelteURLSearchParams('a=b');
const log: any = [];
const cleanup = effect_root(() => {
render_effect(() => {
log.push(params.toString());
});
});
flushSync(() => {
params.set('a', 'c');
});
flushSync(() => {
// nothing should happen here
params.set('a', 'c');
});
assert.deepEqual(log, ['a=b', 'a=c']);
cleanup();
});
test('URLSearchParams.set', () => {
const params = new SvelteURLSearchParams();
const log: any = [];

@ -1,6 +1,14 @@
import { source, set } from '../internal/client/reactivity/sources.js';
import { get } from '../internal/client/runtime.js';
import { onChange, REPLACE, SvelteURLSearchParams } from './url-search-params.js';
import { REPLACE, SvelteURLSearchParams } from './url-search-params.js';
/** @type {SvelteURL | null} */
let current_url = null;
export function get_current_url() {
// ideally we'd just export `current_url` directly, but it seems Vitest doesn't respect live bindings
return current_url;
}
export class SvelteURL extends URL {
#protocol = source(super.protocol);
@ -10,7 +18,8 @@ export class SvelteURL extends URL {
#port = source(super.port);
#pathname = source(super.pathname);
#hash = source(super.hash);
#searchParams = new SvelteURLSearchParams();
#search = source(super.search);
#searchParams;
/**
* @param {string | URL} url
@ -19,18 +28,10 @@ export class SvelteURL extends URL {
constructor(url, base) {
url = new URL(url, base);
super(url);
this.#searchParams[REPLACE](url.searchParams);
this.#searchParams[onChange] = (command, ...args) => {
if (this.search !== super.search) {
super.search = this.search;
}
if (this.#searchParams.toString() === super.searchParams.toString()) {
return;
}
// by doing this, we sync SvelteSearchParams with internal implementation of URL.searchParams
// @ts-expect-error
super.searchParams[command](...args);
};
current_url = this;
this.#searchParams = new SvelteURLSearchParams(url.searchParams);
current_url = null;
}
get hash() {
@ -124,13 +125,13 @@ export class SvelteURL extends URL {
}
get search() {
const search = this.#searchParams?.toString();
return search ? `?${search}` : '';
return get(this.#search);
}
set search(value) {
super.search = value;
this.#searchParams[REPLACE](new URLSearchParams(value.replace(/^\?/, '')));
set(this.#search, value);
this.#searchParams[REPLACE](super.searchParams);
}
get username() {

Loading…
Cancel
Save