breaking: rename svelte/reactivity helpers to include Svelte prefix (#12248)

* breaking: rename svelte/reactivity helpers to include Svelte prefix

* keep old exports

* add runtime errors

* add runtime errors

* feedback

* feedback

* feedback

* Update .changeset/nice-jobs-breathe.md

Co-authored-by: Conduitry <git@chor.date>

---------

Co-authored-by: Conduitry <git@chor.date>
pull/12246/head
Dominic Gannaway 3 days ago committed by GitHub
parent 9a293ea8c4
commit cae5f1ed26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
breaking: rename `svelte/reactivity` helpers to include `Svelte` prefix

@ -57,14 +57,14 @@ const write = [
var inited = false;
export class ReactiveDate extends Date {
export class SvelteDate extends Date {
#raw_time = source(super.getTime());
// We init as part of the first instance so that we can treeshake this class
#init() {
if (!inited) {
inited = true;
const proto = ReactiveDate.prototype;
const proto = SvelteDate.prototype;
const date_proto = Date.prototype;
for (const method of read) {

@ -1,4 +1,29 @@
export { ReactiveDate as Date } from './date.js';
export { ReactiveSet as Set } from './set.js';
export { ReactiveMap as Map } from './map.js';
export { ReactiveURL as URL, ReactiveURLSearchParams as URLSearchParams } from './url.js';
export { SvelteDate } from './date.js';
export { SvelteSet } from './set.js';
export { SvelteMap } from './map.js';
export { SvelteURL, SvelteURLSearchParams } from './url.js';
/** @deprecated Use `SvelteDate` instead */
export function Date() {
throw new Error('Date has been removed, use SvelteDate instead.');
}
/** @deprecated Use `SvelteSet` instead */
export function Set() {
throw new Error('Set has been removed, use SvelteSet instead.');
}
/** @deprecated Use `SvelteMap` instead */
export function Map() {
throw new Error('Map has been removed, use SvelteMap instead.');
}
/** @deprecated Use `SvelteURL` instead */
export function URL() {
throw new Error('URL has been removed, use SvelteURL instead.');
}
/** @deprecated Use `SvelteURLSearchParams` instead */
export function URLSearchParams() {
throw new Error('URLSearchParams has been removed, use SvelteURLSearchParams instead.');
}

@ -1,5 +1,30 @@
export const Date = globalThis.Date;
export const Set = globalThis.Set;
export const Map = globalThis.Map;
export const URL = globalThis.URL;
export const URLSearchParams = globalThis.URLSearchParams;
export const SvelteDate = globalThis.Date;
export const SvelteSet = globalThis.Set;
export const SvelteMap = globalThis.Map;
export const SvelteURL = globalThis.URL;
export const SvelteURLSearchParams = globalThis.URLSearchParams;
/** @deprecated Use `SvelteDate` instead */
export function Date() {
throw new Error('Date has been removed, use SvelteDate instead.');
}
/** @deprecated Use `SvelteSet` instead */
export function Set() {
throw new Error('Set has been removed, use SvelteSet instead.');
}
/** @deprecated Use `SvelteMap` instead */
export function Map() {
throw new Error('Map has been removed, use SvelteMap instead.');
}
/** @deprecated Use `SvelteURL` instead */
export function URL() {
throw new Error('URL has been removed, use SvelteURL instead.');
}
/** @deprecated Use `SvelteURLSearchParams` instead */
export function URLSearchParams() {
throw new Error('URLSearchParams has been removed, use SvelteURLSearchParams instead.');
}

@ -8,7 +8,7 @@ import { increment } from './utils.js';
* @template V
* @extends {Map<K, V>}
*/
export class ReactiveMap extends Map {
export class SvelteMap extends Map {
/** @type {Map<K, import('#client').Source<number>>} */
#sources = new Map();
#version = source(0);

@ -1,10 +1,10 @@
import { render_effect, effect_root } from '../internal/client/reactivity/effects.js';
import { flushSync } from '../index-client.js';
import { ReactiveMap } from './map.js';
import { SvelteMap } from './map.js';
import { assert, test } from 'vitest';
test('map.values()', () => {
const map = new ReactiveMap([
const map = new SvelteMap([
[1, 1],
[2, 2],
[3, 3],
@ -65,7 +65,7 @@ test('map.values()', () => {
});
test('map.get(...)', () => {
const map = new ReactiveMap([
const map = new SvelteMap([
[1, 1],
[2, 2],
[3, 3]
@ -101,7 +101,7 @@ test('map.get(...)', () => {
});
test('map.has(...)', () => {
const map = new ReactiveMap([
const map = new SvelteMap([
[1, 1],
[2, 2],
[3, 3]
@ -148,7 +148,7 @@ test('map.has(...)', () => {
});
test('map.forEach(...)', () => {
const map = new ReactiveMap([
const map = new SvelteMap([
[1, 1],
[2, 2],
[3, 3]
@ -169,7 +169,7 @@ test('map.forEach(...)', () => {
});
test('map.delete(...)', () => {
const map = new ReactiveMap([
const map = new SvelteMap([
[1, 1],
[2, 2],
[3, 3]
@ -182,7 +182,7 @@ test('map.delete(...)', () => {
});
test('map handling of undefined values', () => {
const map = new ReactiveMap();
const map = new SvelteMap();
const log: any = [];
@ -208,7 +208,7 @@ test('map handling of undefined values', () => {
});
test('not invoking reactivity when value is not in the map after changes', () => {
const map = new ReactiveMap([[1, 1]]);
const map = new SvelteMap([[1, 1]]);
const log: any = [];
@ -236,5 +236,5 @@ test('not invoking reactivity when value is not in the map after changes', () =>
});
test('Map.instanceOf', () => {
assert.equal(new ReactiveMap() instanceof Map, true);
assert.equal(new SvelteMap() instanceof Map, true);
});

@ -12,7 +12,7 @@ var inited = false;
* @template T
* @extends {Set<T>}
*/
export class ReactiveSet extends Set {
export class SvelteSet extends Set {
/** @type {Map<T, import('#client').Source<boolean>>} */
#sources = new Map();
#version = source(0);
@ -41,7 +41,7 @@ export class ReactiveSet extends Set {
#init() {
inited = true;
var proto = ReactiveSet.prototype;
var proto = SvelteSet.prototype;
var set_proto = Set.prototype;
for (const method of read_methods) {
@ -59,7 +59,7 @@ export class ReactiveSet extends Set {
get(this.#version);
// @ts-ignore
var set = /** @type {Set<T>} */ (set_proto[method].apply(this, v));
return new ReactiveSet(set);
return new SvelteSet(set);
};
}
}

@ -1,10 +1,10 @@
import { render_effect, effect_root } from '../internal/client/reactivity/effects.js';
import { flushSync } from '../index-client.js';
import { ReactiveSet } from './set.js';
import { SvelteSet } from './set.js';
import { assert, test } from 'vitest';
test('set.values()', () => {
const set = new ReactiveSet([1, 2, 3, 4, 5]);
const set = new SvelteSet([1, 2, 3, 4, 5]);
const log: any = [];
@ -36,7 +36,7 @@ test('set.values()', () => {
});
test('set.has(...)', () => {
const set = new ReactiveSet([1, 2, 3]);
const set = new SvelteSet([1, 2, 3]);
const log: any = [];
@ -79,7 +79,7 @@ test('set.has(...)', () => {
});
test('set.delete(...)', () => {
const set = new ReactiveSet([1, 2, 3]);
const set = new SvelteSet([1, 2, 3]);
assert.equal(set.delete(3), true);
assert.equal(set.delete(3), false);
@ -88,7 +88,7 @@ test('set.delete(...)', () => {
});
test('set.forEach()', () => {
const set = new ReactiveSet([1, 2, 3, 4, 5]);
const set = new SvelteSet([1, 2, 3, 4, 5]);
const log: any = [];
@ -108,7 +108,7 @@ test('set.forEach()', () => {
});
test('not invoking reactivity when value is not in the set after changes', () => {
const set = new ReactiveSet([1, 2]);
const set = new SvelteSet([1, 2]);
const log: any = [];
@ -155,5 +155,5 @@ test('not invoking reactivity when value is not in the set after changes', () =>
});
test('Set.instanceOf', () => {
assert.equal(new ReactiveSet() instanceof Set, true);
assert.equal(new SvelteSet() instanceof Set, true);
});

@ -4,7 +4,7 @@ import { increment } from './utils.js';
const REPLACE = Symbol();
export class ReactiveURL extends URL {
export class SvelteURL extends URL {
#protocol = source(super.protocol);
#username = source(super.username);
#password = source(super.password);
@ -12,7 +12,7 @@ export class ReactiveURL extends URL {
#port = source(super.port);
#pathname = source(super.pathname);
#hash = source(super.hash);
#searchParams = new ReactiveURLSearchParams();
#searchParams = new SvelteURLSearchParams();
/**
* @param {string | URL} url
@ -153,7 +153,7 @@ export class ReactiveURL extends URL {
}
}
export class ReactiveURLSearchParams extends URLSearchParams {
export class SvelteURLSearchParams extends URLSearchParams {
#version = source(0);
/**

@ -1,10 +1,10 @@
import { render_effect, effect_root } from '../internal/client/reactivity/effects.js';
import { flushSync } from '../index-client.js';
import { ReactiveURL, ReactiveURLSearchParams } from './url.js';
import { SvelteURL, SvelteURLSearchParams } from './url.js';
import { assert, test } from 'vitest';
test('url.hash', () => {
const url = new ReactiveURL('http://google.com');
const url = new SvelteURL('http://google.com');
const log: any = [];
const cleanup = effect_root(() => {
@ -32,7 +32,7 @@ test('url.hash', () => {
});
test('url.searchParams', () => {
const url = new ReactiveURL('https://svelte.dev?foo=bar&t=123');
const url = new SvelteURL('https://svelte.dev?foo=bar&t=123');
const log: any = [];
const cleanup = effect_root(() => {
@ -78,7 +78,7 @@ test('url.searchParams', () => {
});
test('URLSearchParams', () => {
const params = new ReactiveURLSearchParams();
const params = new SvelteURLSearchParams();
const log: any = [];
const cleanup = effect_root(() => {

@ -1,7 +1,7 @@
<script>
import { Date } from 'svelte/reactivity';
import { SvelteDate } from 'svelte/reactivity';
let date = new Date('2024-02-23T15:00:00Z');
let date = new SvelteDate('2024-02-23T15:00:00Z');
</script>
<div>getSeconds: {date.getUTCSeconds()}</div>

@ -1,7 +1,7 @@
<script>
import { Map } from 'svelte/reactivity';
import { SvelteMap } from 'svelte/reactivity';
let state = new Map([[0, 0]]);
let state = new SvelteMap([[0, 0]]);
</script>
<button

@ -1,7 +1,7 @@
<script>
import { Set } from 'svelte/reactivity';
import { SvelteSet } from 'svelte/reactivity';
let state = new Set([0]);
let state = new SvelteSet([0]);
</script>
<button onclick={() => state.delete(0)}>delete initial</button>

@ -1,13 +1,13 @@
<script>
import { Set as ReactiveSet, Map as ReactiveMap } from 'svelte/reactivity';
import { SvelteSet, SvelteMap } from 'svelte/reactivity';
let map = new Map();
let set = new Set();
let rmap = new ReactiveMap();
let rset = new ReactiveSet();
let rmap = new SvelteMap();
let rset = new SvelteSet();
</script>
<div>{rset.entries()} {rset.keys()} {rset.values()}</div>
<div>{set.entries()} {set.keys()} {set.values()}</div>
<div>{rmap.entries()} {rmap.keys()} {rmap.values()}</div>
<div>{map.entries()} {map.keys()} {map.values()}</div>
<div>{map.entries()} {map.keys()} {map.values()}</div>

@ -1,7 +1,7 @@
<script>
import { URL } from 'svelte/reactivity';
import { SvelteURL } from 'svelte/reactivity';
let url = new URL('https://svelte.dev/repl/hello-world?version=5.0');
let url = new SvelteURL('https://svelte.dev/repl/hello-world?version=5.0');
</script>
<div>href: {url.href}</div>

@ -1,6 +1,6 @@
<script>
import { Set } from 'svelte/reactivity';
const set = new Set();
import { SvelteSet } from 'svelte/reactivity';
const set = new SvelteSet();
</script>
<form onsubmit={e => {

@ -2131,37 +2131,47 @@ declare module 'svelte/motion' {
}
declare module 'svelte/reactivity' {
class ReactiveDate extends Date {
/** @deprecated Use `SvelteDate` instead */
function Date_1(): void;
/** @deprecated Use `SvelteSet` instead */
function Set_1(): void;
/** @deprecated Use `SvelteMap` instead */
function Map_1(): void;
/** @deprecated Use `SvelteURL` instead */
function URL_1(): void;
/** @deprecated Use `SvelteURLSearchParams` instead */
function URLSearchParams_1(): void;
class SvelteDate extends Date {
constructor(...values: any[]);
#private;
}
class ReactiveSet<T> extends Set<T> {
class SvelteSet<T> extends Set<T> {
constructor(value?: Iterable<T> | null | undefined);
add(value: T): this;
#private;
}
class ReactiveMap<K, V> extends Map<K, V> {
class SvelteMap<K, V> extends Map<K, V> {
constructor(value?: Iterable<readonly [K, V]> | null | undefined);
set(key: K, value: V): this;
#private;
}
class ReactiveURL extends URL {
get searchParams(): ReactiveURLSearchParams;
class SvelteURL extends URL {
get searchParams(): SvelteURLSearchParams;
#private;
}
class ReactiveURLSearchParams extends URLSearchParams {
class SvelteURLSearchParams extends URLSearchParams {
[REPLACE](params: URLSearchParams): void;
#private;
}
const REPLACE: unique symbol;
export { ReactiveDate as Date, ReactiveSet as Set, ReactiveMap as Map, ReactiveURL as URL, ReactiveURLSearchParams as URLSearchParams };
export { Date_1 as Date, Set_1 as Set, Map_1 as Map, URL_1 as URL, URLSearchParams_1 as URLSearchParams, SvelteDate, SvelteSet, SvelteMap, SvelteURL, SvelteURLSearchParams };
}
declare module 'svelte/server' {

@ -95,13 +95,13 @@ To prevent something from being treated as an `$effect`/`$derived` dependency, u
## `svelte/reactivity`
Svelte provides reactive `Map`, `Set`, `Date` and `URL` classes. These can be imported from `svelte/reactivity` and used just like their native counterparts. [Demo:](https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE32QzWrDMBCEX2Wri1uo7bvrBHrvqdBTUogqryuBfhZp5SQYv3slSsmpOc7uN8zsrmI2FpMYDqvw0qEYxCuReBZ8pSrSgpax6BRyVHUyJhUN8f7oj2wchciwwsf7G2wwx-Cg-bX0EaVisxi-Ni-FLbQKPjHkaGEHHs_V9NhoZkpD3-NFOrLYqeB6kqybp-Ia-1uYHx_aFpSW_hsTcADWmLDrOmjbsh-Np8zwZfw0LNJm3K0lqaMYOKhgt_8RHRLX0-8gtdAfUiAdb4XOxlrINElGOOmI8wmkn2AxCmHBmOTdetWw7ct7XZjMbHASA8eM2-f2A-JarmyZAQAA)
Svelte provides reactive `SvelteMap`, `SvelteSet`, `SvelteDate` and `SvelteURL` classes. These can be imported from `svelte/reactivity` and used just like their native counterparts. [Demo:](https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE32QwUrEMBBAf2XMpQrb9t7tFrx7UjxZYWM6NYFkEpJJ16X03yWK9OQeZ3iPecwqZmMxie5tFSQdik48hiAOgq-hDGlByygOIvkcVdn0SUUTeBhpZOOCjwwrvPxgr89PsMEcvYPqV2wjSsVmMXytjiMVR3lKDDlaOAHhZVfvK80cUte2-CVdsNgo79ogWVcPx5H6dj9M_V1dg9KSPjEBe2CNCZumgboeRuoNhczwYWjqFmkzntYcbROiZ6-83f5HtE9c3nADKUF_yEi9jnvQxVgLOUySEc464nwGSRMsRiEsGJO8mVeEbRAH4fxkZoOT6Dhm3N63b9_bGfOlAQAA)
```svelte
<script>
import { URL } from 'svelte/reactivity';
import { SvelteURL } from 'svelte/reactivity';
const url = new URL('https://example.com/path');
const url = new SvelteURL('https://example.com/path');
</script>
<!-- changes to these... -->

Loading…
Cancel
Save