Skip to content

Commit

Permalink
fix: allow $store to be used with changing values including nullish v…
Browse files Browse the repository at this point in the history
…alues (#7947)

fixes #7555
breaking change: derived now throws an error if you pass falsy values

---------

Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
  • Loading branch information
ramonsnir and dummdidumm committed May 4, 2023
1 parent d083f8a commit ea73930
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
* **breaking** Stricter types for `onMount` - now throws a type error when returning a function asynchronously to catch potential mistakes around callback functions (see PR for migration instructions) ([#8136](https://github.com/sveltejs/svelte/pull/8136))
* **breaking** Overhaul and drastically improve creating custom elements with Svelte (see PR for list of changes and migration instructions) ([#8457](https://github.com/sveltejs/svelte/pull/8457))
* **breaking** Deprecate `SvelteComponentTyped`, use `SvelteComponent` instead ([#8512](https://github.com/sveltejs/svelte/pull/8512))
* **breaking** Error on falsy values instead of stores passed to `derived` ([#7947](https://github.com/sveltejs/svelte/pull/7947))
* Add `a11y no-noninteractive-element-interactions` rule ([#8391](https://github.com/sveltejs/svelte/pull/8391))
* Add `a11y-no-static-element-interactions`rule ([#8251](https://github.com/sveltejs/svelte/pull/8251))
* Bind `null` option and input values consistently ([#8312](https://github.com/sveltejs/svelte/issues/8312))
* Allow `$store` to be used with changing values including nullish values ([#7555](https://github.com/sveltejs/svelte/issues/7555))

## Unreleased (3.0)

Expand Down
3 changes: 3 additions & 0 deletions src/runtime/internal/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ export function validate_store(store, name) {

export function subscribe(store, ...callbacks) {
if (store == null) {
for (const callback of callbacks) {
callback(undefined);
}
return noop;
}
const unsub = store.subscribe(...callbacks);
Expand Down
7 changes: 4 additions & 3 deletions src/runtime/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,10 @@ export function derived<S extends Stores, T>(

export function derived<T>(stores: Stores, fn: Function, initial_value?: T): Readable<T> {
const single = !Array.isArray(stores);
const stores_array: Array<Readable<any>> = single
? [stores as Readable<any>]
: stores as Array<Readable<any>>;
const stores_array: Array<Readable<any>> = single ? [stores as Readable<any>] : stores as Array<Readable<any>>;
if (!stores_array.every(Boolean)) {
throw new Error('derived() expects stores as input, got a falsy value');
}

const auto = fn.length < 2;

Expand Down
21 changes: 21 additions & 0 deletions test/runtime/samples/store-auto-subscribe-removed-store/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { writable } from '../../../../store';

export default {
html: `
<p>undefined</p>
`,
async test({ assert, component, target }) {
component.store = writable('foo');
assert.htmlEqual(target.innerHTML, `
<p>foo</p>
`);
component.store = undefined;
assert.htmlEqual(target.innerHTML, `
<p>undefined</p>
`);
component.store = writable('bar');
assert.htmlEqual(target.innerHTML, `
<p>bar</p>
`);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
export let store;
</script>

<p>{$store}</p>
15 changes: 15 additions & 0 deletions test/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,21 @@ describe('store', () => {
a.set(false);
assert.equal(b_started, false);
});

it('errors on undefined stores #1', () => {
assert.throws(() => {
derived(null, (n) => n);
});
});

it('errors on undefined stores #2', () => {
assert.throws(() => {
const a = writable(1);
derived([a, null, undefined], ([n]) => {
return n * 2;
});
});
});
});

describe('get', () => {
Expand Down

0 comments on commit ea73930

Please sign in to comment.