1 | import { noop, safe_not_equal, run_all, is_function } from '../internal';
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | function readable(value, start) {
|
9 | return {
|
10 | subscribe: writable(value, start).subscribe,
|
11 | };
|
12 | }
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | function writable(value, start = noop) {
|
19 | let stop;
|
20 | const subscribers = [];
|
21 | function set(new_value) {
|
22 | if (safe_not_equal(value, new_value)) {
|
23 | value = new_value;
|
24 | if (!stop) {
|
25 | return;
|
26 | }
|
27 | subscribers.forEach((s) => s[1]());
|
28 | subscribers.forEach((s) => s[0](value));
|
29 | }
|
30 | }
|
31 | function update(fn) {
|
32 | set(fn(value));
|
33 | }
|
34 | function subscribe(run, invalidate = noop) {
|
35 | const subscriber = [run, invalidate];
|
36 | subscribers.push(subscriber);
|
37 | if (subscribers.length === 1) {
|
38 | stop = start(set) || noop;
|
39 | }
|
40 | run(value);
|
41 | return () => {
|
42 | const index = subscribers.indexOf(subscriber);
|
43 | if (index !== -1) {
|
44 | subscribers.splice(index, 1);
|
45 | }
|
46 | if (subscribers.length === 0) {
|
47 | stop();
|
48 | }
|
49 | };
|
50 | }
|
51 | return { set, update, subscribe };
|
52 | }
|
53 | /**
|
54 | * Derived value store by synchronizing one or more readable stores and
|
55 | * applying an aggregation function over its input values.
|
56 | * @param {Stores} stores input stores
|
57 | * @param {function(Stores=, function(*)=):*}fn function callback that aggregates the values
|
58 | * @param {*=}initial_value when used asynchronously
|
59 | */
|
60 | function derived(stores, fn, initial_value) {
|
61 | const single = !Array.isArray(stores);
|
62 | const stores_array = single
|
63 | ? [stores]
|
64 | : stores;
|
65 | const auto = fn.length < 2;
|
66 | const invalidators = [];
|
67 | const store = readable(initial_value, (set) => {
|
68 | let inited = false;
|
69 | const values = [];
|
70 | let pending = 0;
|
71 | let cleanup = noop;
|
72 | const sync = () => {
|
73 | if (pending) {
|
74 | return;
|
75 | }
|
76 | cleanup();
|
77 | const result = fn(single ? values[0] : values, set);
|
78 | if (auto) {
|
79 | set(result);
|
80 | }
|
81 | else {
|
82 | cleanup = is_function(result) ? result : noop;
|
83 | }
|
84 | };
|
85 | const unsubscribers = stores_array.map((store, i) => store.subscribe((value) => {
|
86 | values[i] = value;
|
87 | pending &= ~(1 << i);
|
88 | if (inited) {
|
89 | sync();
|
90 | }
|
91 | }, () => {
|
92 | run_all(invalidators);
|
93 | pending |= (1 << i);
|
94 | }));
|
95 | inited = true;
|
96 | sync();
|
97 | return function stop() {
|
98 | run_all(unsubscribers);
|
99 | cleanup();
|
100 | };
|
101 | });
|
102 | return {
|
103 | subscribe(run, invalidate = noop) {
|
104 | invalidators.push(invalidate);
|
105 | const unsubscribe = store.subscribe(run, invalidate);
|
106 | return () => {
|
107 | const index = invalidators.indexOf(invalidate);
|
108 | if (index !== -1) {
|
109 | invalidators.splice(index, 1);
|
110 | }
|
111 | unsubscribe();
|
112 | };
|
113 | }
|
114 | };
|
115 | }
|
116 |
|
117 |
|
118 |
|
119 |
|
120 | function get(store) {
|
121 | let value;
|
122 | store.subscribe((_) => value = _)();
|
123 | return value;
|
124 | }
|
125 |
|
126 | export { readable, writable, derived, get };
|