1 | System.register([], (function (exports) {
|
2 | 'use strict';
|
3 | return {
|
4 | execute: (function () {
|
5 |
|
6 | exports('atom', atom);
|
7 |
|
8 | let keyCount = 0;
|
9 | function atom(read, write) {
|
10 | const key = `atom${++keyCount}`;
|
11 | const config = {
|
12 | toString: () => key
|
13 | };
|
14 | if (typeof read === "function") {
|
15 | config.read = read;
|
16 | } else {
|
17 | config.init = read;
|
18 | config.read = (get) => get(config);
|
19 | config.write = (get, set, arg) => set(
|
20 | config,
|
21 | typeof arg === "function" ? arg(get(config)) : arg
|
22 | );
|
23 | }
|
24 | if (write) {
|
25 | config.write = write;
|
26 | }
|
27 | return config;
|
28 | }
|
29 |
|
30 | const hasInitialValue = (atom) => "init" in atom;
|
31 | const isActuallyWritableAtom = (atom) => !!atom.write;
|
32 | const cancelPromiseMap = new WeakMap();
|
33 | const registerCancelPromise = (promise, cancel) => {
|
34 | cancelPromiseMap.set(promise, cancel);
|
35 | promise.catch(() => {
|
36 | }).finally(() => cancelPromiseMap.delete(promise));
|
37 | };
|
38 | const cancelPromise = (promise, next) => {
|
39 | const cancel = cancelPromiseMap.get(promise);
|
40 | if (cancel) {
|
41 | cancelPromiseMap.delete(promise);
|
42 | cancel(next);
|
43 | }
|
44 | };
|
45 | const resolvePromise = (promise, value) => {
|
46 | promise.status = "fulfilled";
|
47 | promise.value = value;
|
48 | };
|
49 | const rejectPromise = (promise, e) => {
|
50 | promise.status = "rejected";
|
51 | promise.reason = e;
|
52 | };
|
53 | const isEqualAtomValue = (a, b) => "v" in a && "v" in b && Object.is(a.v, b.v);
|
54 | const isEqualAtomError = (a, b) => "e" in a && "e" in b && Object.is(a.e, b.e);
|
55 | const hasPromiseAtomValue = (a) => "v" in a && a.v instanceof Promise;
|
56 | const returnAtomValue = (atomState) => {
|
57 | if ("e" in atomState) {
|
58 | throw atomState.e;
|
59 | }
|
60 | return atomState.v;
|
61 | };
|
62 | const createStore = exports('createStore', () => {
|
63 | const atomStateMap = new WeakMap();
|
64 | const mountedMap = new WeakMap();
|
65 | const pendingMap = new Map();
|
66 | let stateListeners;
|
67 | let mountedAtoms;
|
68 | {
|
69 | stateListeners = new Set();
|
70 | mountedAtoms = new Set();
|
71 | }
|
72 | const getAtomState = (atom) => atomStateMap.get(atom);
|
73 | const setAtomState = (atom, atomState) => {
|
74 | {
|
75 | Object.freeze(atomState);
|
76 | }
|
77 | const prevAtomState = atomStateMap.get(atom);
|
78 | atomStateMap.set(atom, atomState);
|
79 | if (!pendingMap.has(atom)) {
|
80 | pendingMap.set(atom, prevAtomState);
|
81 | }
|
82 | if (prevAtomState && hasPromiseAtomValue(prevAtomState)) {
|
83 | const next = "v" in atomState ? atomState.v instanceof Promise ? atomState.v : Promise.resolve(atomState.v) : Promise.reject(atomState.e);
|
84 | cancelPromise(prevAtomState.v, next);
|
85 | }
|
86 | };
|
87 | const updateDependencies = (atom, nextAtomState, depSet) => {
|
88 | const dependencies = new Map();
|
89 | let changed = false;
|
90 | depSet.forEach((a) => {
|
91 | const aState = a === atom ? nextAtomState : getAtomState(a);
|
92 | if (aState) {
|
93 | dependencies.set(a, aState);
|
94 | if (nextAtomState.d.get(a) !== aState) {
|
95 | changed = true;
|
96 | }
|
97 | } else {
|
98 | console.warn("[Bug] atom state not found");
|
99 | }
|
100 | });
|
101 | if (changed || nextAtomState.d.size !== dependencies.size) {
|
102 | nextAtomState.d = dependencies;
|
103 | }
|
104 | };
|
105 | const setAtomValue = (atom, value, depSet) => {
|
106 | const prevAtomState = getAtomState(atom);
|
107 | const nextAtomState = {
|
108 | d: (prevAtomState == null ? void 0 : prevAtomState.d) || new Map(),
|
109 | v: value
|
110 | };
|
111 | if (depSet) {
|
112 | updateDependencies(atom, nextAtomState, depSet);
|
113 | }
|
114 | if (prevAtomState && isEqualAtomValue(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
|
115 | return prevAtomState;
|
116 | }
|
117 | setAtomState(atom, nextAtomState);
|
118 | return nextAtomState;
|
119 | };
|
120 | const setAtomError = (atom, error, depSet) => {
|
121 | const prevAtomState = getAtomState(atom);
|
122 | const nextAtomState = {
|
123 | d: (prevAtomState == null ? void 0 : prevAtomState.d) || new Map(),
|
124 | e: error
|
125 | };
|
126 | if (depSet) {
|
127 | updateDependencies(atom, nextAtomState, depSet);
|
128 | }
|
129 | if (prevAtomState && isEqualAtomError(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
|
130 | return prevAtomState;
|
131 | }
|
132 | setAtomState(atom, nextAtomState);
|
133 | return nextAtomState;
|
134 | };
|
135 | const readAtomState = (atom) => {
|
136 | const atomState = getAtomState(atom);
|
137 | if (atomState) {
|
138 | atomState.d.forEach((_, a) => {
|
139 | if (a !== atom && !mountedMap.has(a)) {
|
140 | readAtomState(a);
|
141 | }
|
142 | });
|
143 | if (Array.from(atomState.d).every(
|
144 | ([a, s]) => a === atom || getAtomState(a) === s
|
145 | )) {
|
146 | return atomState;
|
147 | }
|
148 | }
|
149 | const depSet = new Set();
|
150 | let isSync = true;
|
151 | const getter = (a) => {
|
152 | depSet.add(a);
|
153 | if (a === atom) {
|
154 | const aState2 = getAtomState(a);
|
155 | if (aState2) {
|
156 | return returnAtomValue(aState2);
|
157 | }
|
158 | if (hasInitialValue(a)) {
|
159 | return a.init;
|
160 | }
|
161 | throw new Error("no atom init");
|
162 | }
|
163 | const aState = readAtomState(a);
|
164 | return returnAtomValue(aState);
|
165 | };
|
166 | let controller;
|
167 | let setSelf;
|
168 | const options = {
|
169 | get signal() {
|
170 | if (!controller) {
|
171 | controller = new AbortController();
|
172 | }
|
173 | return controller.signal;
|
174 | },
|
175 | get setSelf() {
|
176 | if (!isActuallyWritableAtom(atom)) {
|
177 | console.warn("setSelf function cannot be used with read-only atom");
|
178 | }
|
179 | if (!setSelf && isActuallyWritableAtom(atom)) {
|
180 | setSelf = (...args) => {
|
181 | if (isSync) {
|
182 | console.warn("setSelf function cannot be called in sync");
|
183 | }
|
184 | if (!isSync) {
|
185 | return writeAtom(atom, ...args);
|
186 | }
|
187 | };
|
188 | }
|
189 | return setSelf;
|
190 | }
|
191 | };
|
192 | try {
|
193 | const value = atom.read(getter, options);
|
194 | if (value instanceof Promise) {
|
195 | let continuePromise;
|
196 | const promise = new Promise((resolve, reject) => {
|
197 | let settled = false;
|
198 | value.then(
|
199 | (v) => {
|
200 | if (!settled) {
|
201 | resolvePromise(promise, v);
|
202 | resolve(v);
|
203 | }
|
204 | },
|
205 | (e) => {
|
206 | if (!settled) {
|
207 | rejectPromise(promise, e);
|
208 | reject(e);
|
209 | }
|
210 | }
|
211 | ).finally(() => {
|
212 | if (!settled) {
|
213 | settled = true;
|
214 | setAtomValue(atom, promise, depSet);
|
215 | }
|
216 | });
|
217 | continuePromise = (next) => {
|
218 | if (!settled) {
|
219 | settled = true;
|
220 | next.then(
|
221 | (v) => resolvePromise(promise, v),
|
222 | (e) => rejectPromise(promise, e)
|
223 | );
|
224 | resolve(next);
|
225 | }
|
226 | };
|
227 | });
|
228 | promise.status = "pending";
|
229 | registerCancelPromise(promise, (next) => {
|
230 | if (next) {
|
231 | continuePromise(next);
|
232 | }
|
233 | controller == null ? void 0 : controller.abort();
|
234 | });
|
235 | return setAtomValue(atom, promise, depSet);
|
236 | }
|
237 | return setAtomValue(atom, value, depSet);
|
238 | } catch (error) {
|
239 | return setAtomError(atom, error, depSet);
|
240 | } finally {
|
241 | isSync = false;
|
242 | }
|
243 | };
|
244 | const readAtom = (atom) => returnAtomValue(readAtomState(atom));
|
245 | const addAtom = (atom) => {
|
246 | let mounted = mountedMap.get(atom);
|
247 | if (!mounted) {
|
248 | mounted = mountAtom(atom);
|
249 | }
|
250 | return mounted;
|
251 | };
|
252 | const canUnmountAtom = (atom, mounted) => !mounted.l.size && (!mounted.t.size || mounted.t.size === 1 && mounted.t.has(atom));
|
253 | const delAtom = (atom) => {
|
254 | const mounted = mountedMap.get(atom);
|
255 | if (mounted && canUnmountAtom(atom, mounted)) {
|
256 | unmountAtom(atom);
|
257 | }
|
258 | };
|
259 | const recomputeDependents = (atom) => {
|
260 | const mounted = mountedMap.get(atom);
|
261 | mounted == null ? void 0 : mounted.t.forEach((dependent) => {
|
262 | if (dependent !== atom) {
|
263 | const prevAtomState = getAtomState(dependent);
|
264 | const nextAtomState = readAtomState(dependent);
|
265 | if (!prevAtomState || !isEqualAtomValue(prevAtomState, nextAtomState)) {
|
266 | recomputeDependents(dependent);
|
267 | }
|
268 | }
|
269 | });
|
270 | };
|
271 | const writeAtomState = (atom, ...args) => {
|
272 | let isSync = true;
|
273 | const getter = (a) => returnAtomValue(readAtomState(a));
|
274 | const setter = (a, ...args2) => {
|
275 | let r;
|
276 | if (a === atom) {
|
277 | if (!hasInitialValue(a)) {
|
278 | throw new Error("atom not writable");
|
279 | }
|
280 | const prevAtomState = getAtomState(a);
|
281 | const nextAtomState = setAtomValue(a, args2[0]);
|
282 | if (!prevAtomState || !isEqualAtomValue(prevAtomState, nextAtomState)) {
|
283 | recomputeDependents(a);
|
284 | }
|
285 | } else {
|
286 | r = writeAtomState(a, ...args2);
|
287 | }
|
288 | if (!isSync) {
|
289 | flushPending();
|
290 | }
|
291 | return r;
|
292 | };
|
293 | const result = atom.write(getter, setter, ...args);
|
294 | isSync = false;
|
295 | return result;
|
296 | };
|
297 | const writeAtom = (atom, ...args) => {
|
298 | const result = writeAtomState(atom, ...args);
|
299 | flushPending();
|
300 | return result;
|
301 | };
|
302 | const mountAtom = (atom, initialDependent) => {
|
303 | const mounted = {
|
304 | t: new Set(initialDependent && [initialDependent]),
|
305 | l: new Set()
|
306 | };
|
307 | mountedMap.set(atom, mounted);
|
308 | {
|
309 | mountedAtoms.add(atom);
|
310 | }
|
311 | readAtomState(atom).d.forEach((_, a) => {
|
312 | const aMounted = mountedMap.get(a);
|
313 | if (aMounted) {
|
314 | aMounted.t.add(atom);
|
315 | } else {
|
316 | if (a !== atom) {
|
317 | mountAtom(a, atom);
|
318 | }
|
319 | }
|
320 | });
|
321 | readAtomState(atom);
|
322 | if (isActuallyWritableAtom(atom) && atom.onMount) {
|
323 | const onUnmount = atom.onMount((...args) => writeAtom(atom, ...args));
|
324 | if (onUnmount) {
|
325 | mounted.u = onUnmount;
|
326 | }
|
327 | }
|
328 | return mounted;
|
329 | };
|
330 | const unmountAtom = (atom) => {
|
331 | var _a;
|
332 | const onUnmount = (_a = mountedMap.get(atom)) == null ? void 0 : _a.u;
|
333 | if (onUnmount) {
|
334 | onUnmount();
|
335 | }
|
336 | mountedMap.delete(atom);
|
337 | {
|
338 | mountedAtoms.delete(atom);
|
339 | }
|
340 | const atomState = getAtomState(atom);
|
341 | if (atomState) {
|
342 | if (hasPromiseAtomValue(atomState)) {
|
343 | cancelPromise(atomState.v);
|
344 | }
|
345 | atomState.d.forEach((_, a) => {
|
346 | if (a !== atom) {
|
347 | const mounted = mountedMap.get(a);
|
348 | if (mounted) {
|
349 | mounted.t.delete(atom);
|
350 | if (canUnmountAtom(a, mounted)) {
|
351 | unmountAtom(a);
|
352 | }
|
353 | }
|
354 | }
|
355 | });
|
356 | } else {
|
357 | console.warn("[Bug] could not find atom state to unmount", atom);
|
358 | }
|
359 | };
|
360 | const mountDependencies = (atom, atomState, prevDependencies) => {
|
361 | const depSet = new Set(atomState.d.keys());
|
362 | prevDependencies == null ? void 0 : prevDependencies.forEach((_, a) => {
|
363 | if (depSet.has(a)) {
|
364 | depSet.delete(a);
|
365 | return;
|
366 | }
|
367 | const mounted = mountedMap.get(a);
|
368 | if (mounted) {
|
369 | mounted.t.delete(atom);
|
370 | if (canUnmountAtom(a, mounted)) {
|
371 | unmountAtom(a);
|
372 | }
|
373 | }
|
374 | });
|
375 | depSet.forEach((a) => {
|
376 | const mounted = mountedMap.get(a);
|
377 | if (mounted) {
|
378 | mounted.t.add(atom);
|
379 | } else if (mountedMap.has(atom)) {
|
380 | mountAtom(a, atom);
|
381 | }
|
382 | });
|
383 | };
|
384 | const flushPending = () => {
|
385 | while (pendingMap.size) {
|
386 | const pending = Array.from(pendingMap);
|
387 | pendingMap.clear();
|
388 | pending.forEach(([atom, prevAtomState]) => {
|
389 | const atomState = getAtomState(atom);
|
390 | if (atomState) {
|
391 | if (atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) {
|
392 | mountDependencies(atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d);
|
393 | }
|
394 | const mounted = mountedMap.get(atom);
|
395 | if (mounted && !
|
396 |
|
397 | (prevAtomState && !hasPromiseAtomValue(prevAtomState) && (isEqualAtomValue(prevAtomState, atomState) || isEqualAtomError(prevAtomState, atomState)))) {
|
398 | mounted.l.forEach((listener) => listener());
|
399 | }
|
400 | } else {
|
401 | console.warn("[Bug] no atom state to flush");
|
402 | }
|
403 | });
|
404 | }
|
405 | {
|
406 | stateListeners.forEach((l) => l());
|
407 | }
|
408 | };
|
409 | const subscribeAtom = (atom, listener) => {
|
410 | const mounted = addAtom(atom);
|
411 | flushPending();
|
412 | const listeners = mounted.l;
|
413 | listeners.add(listener);
|
414 | return () => {
|
415 | listeners.delete(listener);
|
416 | delAtom(atom);
|
417 | };
|
418 | };
|
419 | {
|
420 | return {
|
421 | get: readAtom,
|
422 | set: writeAtom,
|
423 | sub: subscribeAtom,
|
424 | // store dev methods (these are tentative and subject to change)
|
425 | dev_subscribe_state: (l) => {
|
426 | stateListeners.add(l);
|
427 | return () => {
|
428 | stateListeners.delete(l);
|
429 | };
|
430 | },
|
431 | dev_get_mounted_atoms: () => mountedAtoms.values(),
|
432 | dev_get_atom_state: (a) => atomStateMap.get(a),
|
433 | dev_get_mounted: (a) => mountedMap.get(a),
|
434 | dev_restore_atoms: (values) => {
|
435 | for (const [atom, value] of values) {
|
436 | if (hasInitialValue(atom)) {
|
437 | setAtomValue(atom, value);
|
438 | recomputeDependents(atom);
|
439 | }
|
440 | }
|
441 | flushPending();
|
442 | }
|
443 | };
|
444 | }
|
445 | });
|
446 | let defaultStore;
|
447 | const getDefaultStore = exports('getDefaultStore', () => {
|
448 | if (!defaultStore) {
|
449 | defaultStore = createStore();
|
450 | }
|
451 | return defaultStore;
|
452 | });
|
453 |
|
454 | })
|
455 | };
|
456 | }));
|