UNPKG

21.3 kBJavaScriptView Raw
1System.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 = function(get) {
19 return get(this);
20 };
21 config.write = function(get, set, arg) {
22 return set(
23 this,
24 typeof arg === "function" ? arg(get(this)) : arg
25 );
26 };
27 }
28 if (write) {
29 config.write = write;
30 }
31 return config;
32 }
33
34 const hasInitialValue = (atom) => "init" in atom;
35 const isActuallyWritableAtom = (atom) => !!atom.write;
36 const cancelPromiseMap = /* @__PURE__ */ new WeakMap();
37 const registerCancelPromise = (promise, cancel) => {
38 cancelPromiseMap.set(promise, cancel);
39 promise.catch(() => {
40 }).finally(() => cancelPromiseMap.delete(promise));
41 };
42 const cancelPromise = (promise, next) => {
43 const cancel = cancelPromiseMap.get(promise);
44 if (cancel) {
45 cancelPromiseMap.delete(promise);
46 cancel(next);
47 }
48 };
49 const resolvePromise = (promise, value) => {
50 promise.status = "fulfilled";
51 promise.value = value;
52 };
53 const rejectPromise = (promise, e) => {
54 promise.status = "rejected";
55 promise.reason = e;
56 };
57 const isPromiseLike = (x) => typeof (x == null ? void 0 : x.then) === "function";
58 const isEqualAtomValue = (a, b) => !!a && "v" in a && "v" in b && Object.is(a.v, b.v);
59 const isEqualAtomError = (a, b) => !!a && "e" in a && "e" in b && Object.is(a.e, b.e);
60 const hasPromiseAtomValue = (a) => !!a && "v" in a && a.v instanceof Promise;
61 const isEqualPromiseAtomValue = (a, b) => "v" in a && "v" in b && a.v.orig && a.v.orig === b.v.orig;
62 const returnAtomValue = (atomState) => {
63 if ("e" in atomState) {
64 throw atomState.e;
65 }
66 return atomState.v;
67 };
68 const createStore = exports('createStore', () => {
69 const atomStateMap = /* @__PURE__ */ new WeakMap();
70 const mountedMap = /* @__PURE__ */ new WeakMap();
71 const pendingMap = /* @__PURE__ */ new Map();
72 let storeListenersRev2;
73 let mountedAtoms;
74 {
75 storeListenersRev2 = /* @__PURE__ */ new Set();
76 mountedAtoms = /* @__PURE__ */ new Set();
77 }
78 const getAtomState = (atom) => atomStateMap.get(atom);
79 const setAtomState = (atom, atomState) => {
80 {
81 Object.freeze(atomState);
82 }
83 const prevAtomState = atomStateMap.get(atom);
84 atomStateMap.set(atom, atomState);
85 if (!pendingMap.has(atom)) {
86 pendingMap.set(atom, prevAtomState);
87 }
88 if (hasPromiseAtomValue(prevAtomState)) {
89 const next = "v" in atomState ? atomState.v instanceof Promise ? atomState.v : Promise.resolve(atomState.v) : Promise.reject(atomState.e);
90 if (prevAtomState.v !== next) {
91 cancelPromise(prevAtomState.v, next);
92 }
93 }
94 };
95 const updateDependencies = (atom, nextAtomState, nextDependencies) => {
96 const dependencies = /* @__PURE__ */ new Map();
97 let changed = false;
98 nextDependencies.forEach((aState, a) => {
99 if (!aState && a === atom) {
100 aState = nextAtomState;
101 }
102 if (aState) {
103 dependencies.set(a, aState);
104 if (nextAtomState.d.get(a) !== aState) {
105 changed = true;
106 }
107 } else {
108 console.warn("[Bug] atom state not found");
109 }
110 });
111 if (changed || nextAtomState.d.size !== dependencies.size) {
112 nextAtomState.d = dependencies;
113 }
114 };
115 const setAtomValue = (atom, value, nextDependencies) => {
116 const prevAtomState = getAtomState(atom);
117 const nextAtomState = {
118 d: (prevAtomState == null ? void 0 : prevAtomState.d) || /* @__PURE__ */ new Map(),
119 v: value
120 };
121 if (nextDependencies) {
122 updateDependencies(atom, nextAtomState, nextDependencies);
123 }
124 if (isEqualAtomValue(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
125 return prevAtomState;
126 }
127 if (hasPromiseAtomValue(prevAtomState) && hasPromiseAtomValue(nextAtomState) && isEqualPromiseAtomValue(prevAtomState, nextAtomState)) {
128 if (prevAtomState.d === nextAtomState.d) {
129 return prevAtomState;
130 } else {
131 nextAtomState.v = prevAtomState.v;
132 }
133 }
134 setAtomState(atom, nextAtomState);
135 return nextAtomState;
136 };
137 const setAtomValueOrPromise = (atom, valueOrPromise, nextDependencies, abortPromise) => {
138 if (isPromiseLike(valueOrPromise)) {
139 let continuePromise;
140 const updatePromiseDependencies = () => {
141 const prevAtomState = getAtomState(atom);
142 if (!hasPromiseAtomValue(prevAtomState) || prevAtomState.v !== promise) {
143 return;
144 }
145 const nextAtomState = setAtomValue(
146 atom,
147 promise,
148 nextDependencies
149 );
150 if (mountedMap.has(atom) && prevAtomState.d !== nextAtomState.d) {
151 mountDependencies(atom, nextAtomState, prevAtomState.d);
152 }
153 };
154 const promise = new Promise((resolve, reject) => {
155 let settled = false;
156 valueOrPromise.then(
157 (v) => {
158 if (!settled) {
159 settled = true;
160 resolvePromise(promise, v);
161 resolve(v);
162 updatePromiseDependencies();
163 }
164 },
165 (e) => {
166 if (!settled) {
167 settled = true;
168 rejectPromise(promise, e);
169 reject(e);
170 updatePromiseDependencies();
171 }
172 }
173 );
174 continuePromise = (next) => {
175 if (!settled) {
176 settled = true;
177 next.then(
178 (v) => resolvePromise(promise, v),
179 (e) => rejectPromise(promise, e)
180 );
181 resolve(next);
182 }
183 };
184 });
185 promise.orig = valueOrPromise;
186 promise.status = "pending";
187 registerCancelPromise(promise, (next) => {
188 if (next) {
189 continuePromise(next);
190 }
191 abortPromise == null ? void 0 : abortPromise();
192 });
193 return setAtomValue(atom, promise, nextDependencies);
194 }
195 return setAtomValue(atom, valueOrPromise, nextDependencies);
196 };
197 const setAtomError = (atom, error, nextDependencies) => {
198 const prevAtomState = getAtomState(atom);
199 const nextAtomState = {
200 d: (prevAtomState == null ? void 0 : prevAtomState.d) || /* @__PURE__ */ new Map(),
201 e: error
202 };
203 if (nextDependencies) {
204 updateDependencies(atom, nextAtomState, nextDependencies);
205 }
206 if (isEqualAtomError(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
207 return prevAtomState;
208 }
209 setAtomState(atom, nextAtomState);
210 return nextAtomState;
211 };
212 const readAtomState = (atom, force) => {
213 const atomState = getAtomState(atom);
214 if (!force && atomState) {
215 if (mountedMap.has(atom)) {
216 return atomState;
217 }
218 if (Array.from(atomState.d).every(([a, s]) => {
219 if (a === atom) {
220 return true;
221 }
222 const aState = readAtomState(a);
223 return aState === s || isEqualAtomValue(aState, s);
224 })) {
225 return atomState;
226 }
227 }
228 const nextDependencies = /* @__PURE__ */ new Map();
229 let isSync = true;
230 const getter = (a) => {
231 if (a === atom) {
232 const aState2 = getAtomState(a);
233 if (aState2) {
234 nextDependencies.set(a, aState2);
235 return returnAtomValue(aState2);
236 }
237 if (hasInitialValue(a)) {
238 nextDependencies.set(a, void 0);
239 return a.init;
240 }
241 throw new Error("no atom init");
242 }
243 const aState = readAtomState(a);
244 nextDependencies.set(a, aState);
245 return returnAtomValue(aState);
246 };
247 let controller;
248 let setSelf;
249 const options = {
250 get signal() {
251 if (!controller) {
252 controller = new AbortController();
253 }
254 return controller.signal;
255 },
256 get setSelf() {
257 if (!isActuallyWritableAtom(atom)) {
258 console.warn("setSelf function cannot be used with read-only atom");
259 }
260 if (!setSelf && isActuallyWritableAtom(atom)) {
261 setSelf = (...args) => {
262 if (isSync) {
263 console.warn("setSelf function cannot be called in sync");
264 }
265 if (!isSync) {
266 return writeAtom(atom, ...args);
267 }
268 };
269 }
270 return setSelf;
271 }
272 };
273 try {
274 const valueOrPromise = atom.read(getter, options);
275 return setAtomValueOrPromise(
276 atom,
277 valueOrPromise,
278 nextDependencies,
279 () => controller == null ? void 0 : controller.abort()
280 );
281 } catch (error) {
282 return setAtomError(atom, error, nextDependencies);
283 } finally {
284 isSync = false;
285 }
286 };
287 const readAtom = (atom) => returnAtomValue(readAtomState(atom));
288 const addAtom = (atom) => {
289 let mounted = mountedMap.get(atom);
290 if (!mounted) {
291 mounted = mountAtom(atom);
292 }
293 return mounted;
294 };
295 const canUnmountAtom = (atom, mounted) => !mounted.l.size && (!mounted.t.size || mounted.t.size === 1 && mounted.t.has(atom));
296 const delAtom = (atom) => {
297 const mounted = mountedMap.get(atom);
298 if (mounted && canUnmountAtom(atom, mounted)) {
299 unmountAtom(atom);
300 }
301 };
302 const recomputeDependents = (atom) => {
303 const dependencyMap = /* @__PURE__ */ new Map();
304 const dirtyMap = /* @__PURE__ */ new WeakMap();
305 const getDependents = (a) => {
306 var _a;
307 const dependents = new Set((_a = mountedMap.get(a)) == null ? void 0 : _a.t);
308 pendingMap.forEach((_, pendingAtom) => {
309 var _a2;
310 if ((_a2 = getAtomState(pendingAtom)) == null ? void 0 : _a2.d.has(a)) {
311 dependents.add(pendingAtom);
312 }
313 });
314 return dependents;
315 };
316 const loop1 = (a) => {
317 getDependents(a).forEach((dependent) => {
318 if (dependent !== a) {
319 dependencyMap.set(
320 dependent,
321 (dependencyMap.get(dependent) || /* @__PURE__ */ new Set()).add(a)
322 );
323 dirtyMap.set(dependent, (dirtyMap.get(dependent) || 0) + 1);
324 loop1(dependent);
325 }
326 });
327 };
328 loop1(atom);
329 const loop2 = (a) => {
330 getDependents(a).forEach((dependent) => {
331 var _a;
332 if (dependent !== a) {
333 let dirtyCount = dirtyMap.get(dependent);
334 if (dirtyCount) {
335 dirtyMap.set(dependent, --dirtyCount);
336 }
337 if (!dirtyCount) {
338 let isChanged = !!((_a = dependencyMap.get(dependent)) == null ? void 0 : _a.size);
339 if (isChanged) {
340 const prevAtomState = getAtomState(dependent);
341 const nextAtomState = readAtomState(dependent, true);
342 isChanged = !isEqualAtomValue(prevAtomState, nextAtomState);
343 }
344 if (!isChanged) {
345 dependencyMap.forEach((s) => s.delete(dependent));
346 }
347 }
348 loop2(dependent);
349 }
350 });
351 };
352 loop2(atom);
353 };
354 const writeAtomState = (atom, ...args) => {
355 let isSync = true;
356 const getter = (a) => returnAtomValue(readAtomState(a));
357 const setter = (a, ...args2) => {
358 let r;
359 if (a === atom) {
360 if (!hasInitialValue(a)) {
361 throw new Error("atom not writable");
362 }
363 const prevAtomState = getAtomState(a);
364 const nextAtomState = setAtomValueOrPromise(a, args2[0]);
365 if (!isEqualAtomValue(prevAtomState, nextAtomState)) {
366 recomputeDependents(a);
367 }
368 } else {
369 r = writeAtomState(a, ...args2);
370 }
371 if (!isSync) {
372 const flushed = flushPending();
373 {
374 storeListenersRev2.forEach(
375 (l) => l({ type: "async-write", flushed })
376 );
377 }
378 }
379 return r;
380 };
381 const result = atom.write(getter, setter, ...args);
382 isSync = false;
383 return result;
384 };
385 const writeAtom = (atom, ...args) => {
386 const result = writeAtomState(atom, ...args);
387 const flushed = flushPending();
388 {
389 storeListenersRev2.forEach(
390 (l) => l({ type: "write", flushed })
391 );
392 }
393 return result;
394 };
395 const mountAtom = (atom, initialDependent, onMountQueue) => {
396 var _a;
397 const queue = onMountQueue || [];
398 (_a = getAtomState(atom)) == null ? void 0 : _a.d.forEach((_, a) => {
399 const aMounted = mountedMap.get(a);
400 if (aMounted) {
401 aMounted.t.add(atom);
402 } else {
403 if (a !== atom) {
404 mountAtom(a, atom, queue);
405 }
406 }
407 });
408 readAtomState(atom);
409 const mounted = {
410 t: new Set(initialDependent && [initialDependent]),
411 l: /* @__PURE__ */ new Set()
412 };
413 mountedMap.set(atom, mounted);
414 {
415 mountedAtoms.add(atom);
416 }
417 if (isActuallyWritableAtom(atom) && atom.onMount) {
418 const { onMount } = atom;
419 queue.push(() => {
420 const onUnmount = onMount((...args) => writeAtom(atom, ...args));
421 if (onUnmount) {
422 mounted.u = onUnmount;
423 }
424 });
425 }
426 if (!onMountQueue) {
427 queue.forEach((f) => f());
428 }
429 return mounted;
430 };
431 const unmountAtom = (atom) => {
432 var _a;
433 const onUnmount = (_a = mountedMap.get(atom)) == null ? void 0 : _a.u;
434 if (onUnmount) {
435 onUnmount();
436 }
437 mountedMap.delete(atom);
438 {
439 mountedAtoms.delete(atom);
440 }
441 const atomState = getAtomState(atom);
442 if (atomState) {
443 if (hasPromiseAtomValue(atomState)) {
444 cancelPromise(atomState.v);
445 }
446 atomState.d.forEach((_, a) => {
447 if (a !== atom) {
448 const mounted = mountedMap.get(a);
449 if (mounted) {
450 mounted.t.delete(atom);
451 if (canUnmountAtom(a, mounted)) {
452 unmountAtom(a);
453 }
454 }
455 }
456 });
457 } else {
458 console.warn("[Bug] could not find atom state to unmount", atom);
459 }
460 };
461 const mountDependencies = (atom, atomState, prevDependencies) => {
462 const depSet = new Set(atomState.d.keys());
463 prevDependencies == null ? void 0 : prevDependencies.forEach((_, a) => {
464 if (depSet.has(a)) {
465 depSet.delete(a);
466 return;
467 }
468 const mounted = mountedMap.get(a);
469 if (mounted) {
470 mounted.t.delete(atom);
471 if (canUnmountAtom(a, mounted)) {
472 unmountAtom(a);
473 }
474 }
475 });
476 depSet.forEach((a) => {
477 const mounted = mountedMap.get(a);
478 if (mounted) {
479 mounted.t.add(atom);
480 } else if (mountedMap.has(atom)) {
481 mountAtom(a, atom);
482 }
483 });
484 };
485 const flushPending = () => {
486 let flushed;
487 {
488 flushed = /* @__PURE__ */ new Set();
489 }
490 while (pendingMap.size) {
491 const pending = Array.from(pendingMap);
492 pendingMap.clear();
493 pending.forEach(([atom, prevAtomState]) => {
494 const atomState = getAtomState(atom);
495 if (atomState) {
496 const mounted = mountedMap.get(atom);
497 if (mounted && atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) {
498 mountDependencies(atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d);
499 }
500 if (mounted && !// TODO This seems pretty hacky. Hope to fix it.
501 // Maybe we could `mountDependencies` in `setAtomState`?
502 (!hasPromiseAtomValue(prevAtomState) && (isEqualAtomValue(prevAtomState, atomState) || isEqualAtomError(prevAtomState, atomState)))) {
503 mounted.l.forEach((listener) => listener());
504 {
505 flushed.add(atom);
506 }
507 }
508 } else {
509 console.warn("[Bug] no atom state to flush");
510 }
511 });
512 }
513 {
514 return flushed;
515 }
516 };
517 const subscribeAtom = (atom, listener) => {
518 const mounted = addAtom(atom);
519 const flushed = flushPending();
520 const listeners = mounted.l;
521 listeners.add(listener);
522 {
523 storeListenersRev2.forEach(
524 (l) => l({ type: "sub", flushed })
525 );
526 }
527 return () => {
528 listeners.delete(listener);
529 delAtom(atom);
530 {
531 storeListenersRev2.forEach((l) => l({ type: "unsub" }));
532 }
533 };
534 };
535 {
536 return {
537 get: readAtom,
538 set: writeAtom,
539 sub: subscribeAtom,
540 // store dev methods (these are tentative and subject to change without notice)
541 dev_subscribe_store: (l, rev) => {
542 if (rev !== 2) {
543 throw new Error("The current StoreListener revision is 2.");
544 }
545 storeListenersRev2.add(l);
546 return () => {
547 storeListenersRev2.delete(l);
548 };
549 },
550 dev_get_mounted_atoms: () => mountedAtoms.values(),
551 dev_get_atom_state: (a) => atomStateMap.get(a),
552 dev_get_mounted: (a) => mountedMap.get(a),
553 dev_restore_atoms: (values) => {
554 for (const [atom, valueOrPromise] of values) {
555 if (hasInitialValue(atom)) {
556 setAtomValueOrPromise(atom, valueOrPromise);
557 recomputeDependents(atom);
558 }
559 }
560 const flushed = flushPending();
561 storeListenersRev2.forEach(
562 (l) => l({ type: "restore", flushed })
563 );
564 }
565 };
566 }
567 });
568 let defaultStore;
569 {
570 if (typeof globalThis.__NUMBER_OF_JOTAI_INSTANCES__ === "number") {
571 ++globalThis.__NUMBER_OF_JOTAI_INSTANCES__;
572 } else {
573 globalThis.__NUMBER_OF_JOTAI_INSTANCES__ = 1;
574 }
575 }
576 const getDefaultStore = exports('getDefaultStore', () => {
577 if (!defaultStore) {
578 if (globalThis.__NUMBER_OF_JOTAI_INSTANCES__ !== 1) {
579 console.warn(
580 "Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044"
581 );
582 }
583 defaultStore = createStore();
584 }
585 return defaultStore;
586 });
587
588 })
589 };
590}));