diff --git a/src/runtime/store/index.ts b/src/runtime/store/index.ts index e7db228401..ef08e931c9 100644 --- a/src/runtime/store/index.ts +++ b/src/runtime/store/index.ts @@ -1,4 +1,4 @@ -import { run_all, noop, safe_not_equal, is_function } from 'svelte/internal'; +import { run_all, noop, not_equal, safe_not_equal, is_function } from 'svelte/internal'; /** Callback to inform of a value updates. */ type Subscriber = (value: T) => void; @@ -54,17 +54,34 @@ export function readable(value: T, start: StartStopNotifier): Readable }; } +interface WritableOptions { + /** Start and stop notifications for subscriptions */ + start?: StartStopNotifier; + /** Use immutable equality comparison */ + immutable?: boolean; +} + /** * Create a `Writable` store that allows both updating and reading by subscription. - * @param {*=}value initial value - * @param {StartStopNotifier=}start start and stop notifications for subscriptions + * @param {*=} value initial value + * @param {StartStopNotifier|WritableOptions?} options start and stop notifications for subscriptions or options */ -export function writable(value: T, start: StartStopNotifier = noop): Writable { +export function writable( + value: T, + options?: StartStopNotifier | WritableOptions, +): Writable { let stop: Unsubscriber; const subscribers: Array> = []; + let start: StartStopNotifier = noop; + if (typeof options === "function") { + start = options; + } else if (typeof options === "object" && options.start) { + start = options.start; + } + const not_equal_compare = typeof options === "object" && options.immutable ? not_equal : safe_not_equal; function set(new_value: T): void { - if (safe_not_equal(value, new_value)) { + if (not_equal_compare(value, new_value)) { value = new_value; if (!stop) { return; // not ready diff --git a/test/store/index.ts b/test/store/index.ts index 13b8e1f869..1f72c9e701 100644 --- a/test/store/index.ts +++ b/test/store/index.ts @@ -278,6 +278,22 @@ describe('store', () => { b.set(2); assert.deepEqual(get(c), 'two 2'); }); + + it('allows immutable stores', () => { + const obj = { value: 1 }; + const a = writable(obj, { immutable: true }); + let called = 0; + a.subscribe(() => { + called++; + }) + + assert.equal(called, 1); + obj.value += 1; + a.set(obj); + assert.equal(called, 1); + a.set({ value: 2 }); + assert.equal(called, 2); + }); }); describe('get', () => {