fix: avoid tracking SvelteURLSearchParams during URL updates (#18791)

### Before submitting the PR, please make sure you do the following

- [x] It's really useful if your PR references an issue where it is
discussed ahead of time. In many cases, features are absent for a
reason. For large changes, please create an RFC:
https://github.com/sveltejs/rfcs
- [x] Prefix your PR title with `feat:`, `fix:`, `chore:`, or `docs:`.
- [ ] This message body should clearly illustrate what problems it
solves.
- [ ] Ideally, include a test that fails without this PR but passes with
it.
- [ ] If this PR changes code within `packages/svelte/src`, add a
changeset (`npx changeset`).

### Tests and linting

- [x] Run the tests with `pnpm test` and lint the project with `pnpm
lint`


---


Avoids creating an unintended reactive dependency when
`SvelteURLSearchParams` synchronizes its owning `SvelteURL`.

`#update_url()` now uses `super.toString()` instead of the reactive
`toString()` method. URL synchronization only needs native serialization
and should not subscribe the current reaction to the params version
signal.


Before this change, code such as:

```js
render_effect(() => {
	url.searchParams.set('foo', 'bar');
});
```


could cause the effect to run twice:

1. set() calls #update_url()
2. #update_url() calls reactive toString()
3. toString() subscribes the effect to #version
4. set() increments #version
5. The effect is scheduled again

Signed-off-by: cuishuang <imcusg@gmail.com>
pull/18927/merge
cui fliter 18 hours ago committed by GitHub
parent 7c2fcdae6a
commit 7e83327400
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: avoid tracking SvelteURLSearchParams during URL updates

@ -42,7 +42,7 @@ export class SvelteURLSearchParams extends URLSearchParams {
if (!this.#url || this.#updating) return;
this.#updating = true;
const search = this.toString();
const search = super.toString();
this.#url.search = search && `?${search}`;
this.#updating = false;

@ -115,6 +115,24 @@ test('url.searchParams', () => {
cleanup();
});
test('url.searchParams writes do not create a reactive dependency', () => {
const url = new SvelteURL('https://svelte.dev');
let runs = 0;
const cleanup = effect_root(() => {
render_effect(() => {
runs += 1;
url.searchParams.set('foo', 'bar');
});
});
flushSync();
assert.equal(runs, 1);
cleanup();
});
test('url.searchParams.set updates url when duplicate values collapse to the same joined string', () => {
const url = new SvelteURL('https://svelte.dev?a=ab&a=c');
const log: any = [];

Loading…
Cancel
Save