UNPKG

3.32 kBJavaScriptView Raw
1import { noop, safe_not_equal, subscribe, run_all, is_function } from '../internal/index.mjs';
2export { get_store_value as get } from '../internal/index.mjs';
3
4const subscriber_queue = [];
5/**
6 * Creates a `Readable` store that allows reading by subscription.
7 * @param value initial value
8 * @param {StartStopNotifier}start start and stop notifications for subscriptions
9 */
10function readable(value, start) {
11 return {
12 subscribe: writable(value, start).subscribe
13 };
14}
15/**
16 * Create a `Writable` store that allows both updating and reading by subscription.
17 * @param {*=}value initial value
18 * @param {StartStopNotifier=}start start and stop notifications for subscriptions
19 */
20function writable(value, start = noop) {
21 let stop;
22 const subscribers = [];
23 function set(new_value) {
24 if (safe_not_equal(value, new_value)) {
25 value = new_value;
26 if (stop) { // store is ready
27 const run_queue = !subscriber_queue.length;
28 for (let i = 0; i < subscribers.length; i += 1) {
29 const s = subscribers[i];
30 s[1]();
31 subscriber_queue.push(s, value);
32 }
33 if (run_queue) {
34 for (let i = 0; i < subscriber_queue.length; i += 2) {
35 subscriber_queue[i][0](subscriber_queue[i + 1]);
36 }
37 subscriber_queue.length = 0;
38 }
39 }
40 }
41 }
42 function update(fn) {
43 set(fn(value));
44 }
45 function subscribe(run, invalidate = noop) {
46 const subscriber = [run, invalidate];
47 subscribers.push(subscriber);
48 if (subscribers.length === 1) {
49 stop = start(set) || noop;
50 }
51 run(value);
52 return () => {
53 const index = subscribers.indexOf(subscriber);
54 if (index !== -1) {
55 subscribers.splice(index, 1);
56 }
57 if (subscribers.length === 0) {
58 stop();
59 stop = null;
60 }
61 };
62 }
63 return { set, update, subscribe };
64}
65function derived(stores, fn, initial_value) {
66 const single = !Array.isArray(stores);
67 const stores_array = single
68 ? [stores]
69 : stores;
70 const auto = fn.length < 2;
71 return readable(initial_value, (set) => {
72 let inited = false;
73 const values = [];
74 let pending = 0;
75 let cleanup = noop;
76 const sync = () => {
77 if (pending) {
78 return;
79 }
80 cleanup();
81 const result = fn(single ? values[0] : values, set);
82 if (auto) {
83 set(result);
84 }
85 else {
86 cleanup = is_function(result) ? result : noop;
87 }
88 };
89 const unsubscribers = stores_array.map((store, i) => subscribe(store, (value) => {
90 values[i] = value;
91 pending &= ~(1 << i);
92 if (inited) {
93 sync();
94 }
95 }, () => {
96 pending |= (1 << i);
97 }));
98 inited = true;
99 sync();
100 return function stop() {
101 run_all(unsubscribers);
102 cleanup();
103 };
104 });
105}
106
107export { derived, readable, writable };