fix: lift unsafe_state_mutation constrained for SvelteDate, SvelteURL and SvelteURLSearchParams created inside the derived

pull/16221/head
Fedor Nezhivoi 3 months ago
parent 3c3255fdb9
commit a784607811

@ -2,4 +2,4 @@
'svelte': patch
---
lift unsafe_state_mutation constrained for SvelteSet and SvelteMap created inside the derived
lift unsafe_state_mutation constraints for SvelteSet, SvelteMap, SvelteDate, SvelteURL and SvelteURLSearchParams created inside the derived

@ -1,6 +1,6 @@
/** @import { Source } from '#client' */
import { derived } from '../internal/client/index.js';
import { source, set } from '../internal/client/reactivity/sources.js';
import { set, state } from '../internal/client/reactivity/sources.js';
import { tag } from '../internal/client/dev/tracing.js';
import { active_reaction, get, set_active_reaction } from '../internal/client/runtime.js';
import { DEV } from 'esm-env';
@ -40,7 +40,7 @@ var inited = false;
* ```
*/
export class SvelteDate extends Date {
#time = source(super.getTime());
#time = state(super.getTime());
/** @type {Map<keyof Date, Source<unknown>>} */
#deriveds = new Map();

@ -1,5 +1,5 @@
import { DEV } from 'esm-env';
import { source } from '../internal/client/reactivity/sources.js';
import { state } from '../internal/client/reactivity/sources.js';
import { tag } from '../internal/client/dev/tracing.js';
import { get } from '../internal/client/runtime.js';
import { get_current_url } from './url.js';
@ -34,7 +34,7 @@ export const REPLACE = Symbol();
* ```
*/
export class SvelteURLSearchParams extends URLSearchParams {
#version = DEV ? tag(source(0), 'SvelteURLSearchParams version') : source(0);
#version = DEV ? tag(state(0), 'SvelteURLSearchParams version') : state(0);
#url = get_current_url();
#updating = false;

@ -1,5 +1,5 @@
import { DEV } from 'esm-env';
import { source, set } from '../internal/client/reactivity/sources.js';
import { set, state } from '../internal/client/reactivity/sources.js';
import { tag } from '../internal/client/dev/tracing.js';
import { get } from '../internal/client/runtime.js';
import { REPLACE, SvelteURLSearchParams } from './url-search-params.js';
@ -40,14 +40,14 @@ export function get_current_url() {
* ```
*/
export class SvelteURL extends URL {
#protocol = source(super.protocol);
#username = source(super.username);
#password = source(super.password);
#hostname = source(super.hostname);
#port = source(super.port);
#pathname = source(super.pathname);
#hash = source(super.hash);
#search = source(super.search);
#protocol = state(super.protocol);
#username = state(super.username);
#password = state(super.password);
#hostname = state(super.hostname);
#port = state(super.port);
#pathname = state(super.pathname);
#hash = state(super.hash);
#search = state(super.search);
#searchParams;
/**

@ -0,0 +1,23 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
compileOptions: {
dev: true,
runes: true
},
test({ assert, target }) {
const [button1, button2] = target.querySelectorAll('button');
assert.throws(() => {
button1?.click();
flushSync();
}, /state_unsafe_mutation/);
assert.doesNotThrow(() => {
button2?.click();
flushSync();
});
}
});

@ -0,0 +1,27 @@
<script>
import { SvelteDate } from 'svelte/reactivity';
let visibleExternal = $state(false);
let external = new SvelteDate();
const throws = $derived.by(() => {
external.setTime(12345);
return external;
})
let visibleInternal = $state(false);
const works = $derived.by(() => {
let internal = new SvelteDate();
internal.setTime(12345);
return internal;
})
</script>
<button onclick={() => (visibleExternal = true)}>external</button>
{#if visibleExternal}
{throws}
{/if}
<button onclick={() => (visibleInternal = true)}>internal</button>
{#if visibleInternal}
{works}
{/if}

@ -0,0 +1,23 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
compileOptions: {
dev: true,
runes: true
},
test({ assert, target }) {
const [button1, button2] = target.querySelectorAll('button');
assert.throws(() => {
button1?.click();
flushSync();
}, /state_unsafe_mutation/);
assert.doesNotThrow(() => {
button2?.click();
flushSync();
});
}
});

@ -0,0 +1,27 @@
<script>
import { SvelteURLSearchParams } from 'svelte/reactivity';
let visibleExternal = $state(false);
let external = new SvelteURLSearchParams();
const throws = $derived.by(() => {
external.append('foo', 'bar')
return external;
})
let visibleInternal = $state(false);
const works = $derived.by(() => {
let internal = new SvelteURLSearchParams();
internal.append('foo', 'bar')
return internal;
})
</script>
<button onclick={() => (visibleExternal = true)}>external</button>
{#if visibleExternal}
{throws}
{/if}
<button onclick={() => (visibleInternal = true)}>internal</button>
{#if visibleInternal}
{works}
{/if}

@ -0,0 +1,23 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
compileOptions: {
dev: true,
runes: true
},
test({ assert, target }) {
const [button1, button2] = target.querySelectorAll('button');
assert.throws(() => {
button1?.click();
flushSync();
}, /state_unsafe_mutation/);
assert.doesNotThrow(() => {
button2?.click();
flushSync();
});
}
});

@ -0,0 +1,27 @@
<script>
import { SvelteURL } from 'svelte/reactivity';
let visibleExternal = $state(false);
let external = new SvelteURL('https://svelte.dev');
const throws = $derived.by(() => {
external.host = 'kit.svelte.dev'
return external;
})
let visibleInternal = $state(false);
const works = $derived.by(() => {
let internal = new SvelteURL('https://svelte.dev');
internal.host = 'kit.svelte.dev'
return internal;
})
</script>
<button onclick={() => (visibleExternal = true)}>external</button>
{#if visibleExternal}
{throws}
{/if}
<button onclick={() => (visibleInternal = true)}>internal</button>
{#if visibleInternal}
{works}
{/if}
Loading…
Cancel
Save