diff options
Diffstat (limited to 'node_modules/svelte/src/runtime/store')
| -rw-r--r-- | node_modules/svelte/src/runtime/store/index.js | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/node_modules/svelte/src/runtime/store/index.js b/node_modules/svelte/src/runtime/store/index.js new file mode 100644 index 0000000..e5827ff --- /dev/null +++ b/node_modules/svelte/src/runtime/store/index.js @@ -0,0 +1,199 @@ +import { + run_all, + subscribe, + noop, + safe_not_equal, + is_function, + get_store_value +} from '../internal/index.js'; + +const subscriber_queue = []; + +/** + * Creates a `Readable` store that allows reading by subscription. + * + * https://svelte.dev/docs/svelte-store#readable + * @template T + * @param {T} [value] initial value + * @param {import('./public.js').StartStopNotifier<T>} [start] + * @returns {import('./public.js').Readable<T>} + */ +export function readable(value, start) { + return { + subscribe: writable(value, start).subscribe + }; +} + +/** + * Create a `Writable` store that allows both updating and reading by subscription. + * + * https://svelte.dev/docs/svelte-store#writable + * @template T + * @param {T} [value] initial value + * @param {import('./public.js').StartStopNotifier<T>} [start] + * @returns {import('./public.js').Writable<T>} + */ +export function writable(value, start = noop) { + /** @type {import('./public.js').Unsubscriber} */ + let stop; + /** @type {Set<import('./private.js').SubscribeInvalidateTuple<T>>} */ + const subscribers = new Set(); + /** @param {T} new_value + * @returns {void} + */ + function set(new_value) { + if (safe_not_equal(value, new_value)) { + value = new_value; + if (stop) { + // store is ready + const run_queue = !subscriber_queue.length; + for (const subscriber of subscribers) { + subscriber[1](); + subscriber_queue.push(subscriber, value); + } + if (run_queue) { + for (let i = 0; i < subscriber_queue.length; i += 2) { + subscriber_queue[i][0](subscriber_queue[i + 1]); + } + subscriber_queue.length = 0; + } + } + } + } + + /** + * @param {import('./public.js').Updater<T>} fn + * @returns {void} + */ + function update(fn) { + set(fn(value)); + } + + /** + * @param {import('./public.js').Subscriber<T>} run + * @param {import('./private.js').Invalidator<T>} [invalidate] + * @returns {import('./public.js').Unsubscriber} + */ + function subscribe(run, invalidate = noop) { + /** @type {import('./private.js').SubscribeInvalidateTuple<T>} */ + const subscriber = [run, invalidate]; + subscribers.add(subscriber); + if (subscribers.size === 1) { + stop = start(set, update) || noop; + } + run(value); + return () => { + subscribers.delete(subscriber); + if (subscribers.size === 0 && stop) { + stop(); + stop = null; + } + }; + } + return { set, update, subscribe }; +} + +/** + * Derived value store by synchronizing one or more readable stores and + * applying an aggregation function over its input values. + * + * https://svelte.dev/docs/svelte-store#derived + * @template {import('./private.js').Stores} S + * @template T + * @overload + * @param {S} stores - input stores + * @param {(values: import('./private.js').StoresValues<S>, set: (value: T) => void, update: (fn: import('./public.js').Updater<T>) => void) => import('./public.js').Unsubscriber | void} fn - function callback that aggregates the values + * @param {T} [initial_value] - initial value + * @returns {import('./public.js').Readable<T>} + */ + +/** + * Derived value store by synchronizing one or more readable stores and + * applying an aggregation function over its input values. + * + * https://svelte.dev/docs/svelte-store#derived + * @template {import('./private.js').Stores} S + * @template T + * @overload + * @param {S} stores - input stores + * @param {(values: import('./private.js').StoresValues<S>) => T} fn - function callback that aggregates the values + * @param {T} [initial_value] - initial value + * @returns {import('./public.js').Readable<T>} + */ + +/** + * @template {import('./private.js').Stores} S + * @template T + * @param {S} stores + * @param {Function} fn + * @param {T} [initial_value] + * @returns {import('./public.js').Readable<T>} + */ +export function derived(stores, fn, initial_value) { + const single = !Array.isArray(stores); + /** @type {Array<import('./public.js').Readable<any>>} */ + const stores_array = single ? [stores] : stores; + if (!stores_array.every(Boolean)) { + throw new Error('derived() expects stores as input, got a falsy value'); + } + const auto = fn.length < 2; + return readable(initial_value, (set, update) => { + let started = false; + const values = []; + let pending = 0; + let cleanup = noop; + const sync = () => { + if (pending) { + return; + } + cleanup(); + const result = fn(single ? values[0] : values, set, update); + if (auto) { + set(result); + } else { + cleanup = is_function(result) ? result : noop; + } + }; + const unsubscribers = stores_array.map((store, i) => + subscribe( + store, + (value) => { + values[i] = value; + pending &= ~(1 << i); + if (started) { + sync(); + } + }, + () => { + pending |= 1 << i; + } + ) + ); + started = true; + sync(); + return function stop() { + run_all(unsubscribers); + cleanup(); + // We need to set this to false because callbacks can still happen despite having unsubscribed: + // Callbacks might already be placed in the queue which doesn't know it should no longer + // invoke this derived store. + started = false; + }; + }); +} + +/** + * Takes a store and returns a new one derived from the old one that is readable. + * + * https://svelte.dev/docs/svelte-store#readonly + * @template T + * @param {import('./public.js').Readable<T>} store - store to make readonly + * @returns {import('./public.js').Readable<T>} + */ +export function readonly(store) { + return { + subscribe: store.subscribe.bind(store) + }; +} + +export { get_store_value as get }; |
