UNPKG

22.5 kBJavaScriptView Raw
1'use strict';
2
3var keyCount = 0;
4function atom(read, write) {
5 var key = "atom" + ++keyCount;
6 var config = {
7 toString: function toString() {
8 return key;
9 }
10 };
11 if (typeof read === 'function') {
12 config.read = read;
13 } else {
14 config.init = read;
15 config.read = function (get) {
16 return get(config);
17 };
18 config.write = function (get, set, arg) {
19 return set(config, typeof arg === 'function' ? arg(get(config)) : arg);
20 };
21 }
22 if (write) {
23 config.write = write;
24 }
25 return config;
26}
27
28function _unsupportedIterableToArray(o, minLen) {
29 if (!o) return;
30 if (typeof o === "string") return _arrayLikeToArray(o, minLen);
31 var n = Object.prototype.toString.call(o).slice(8, -1);
32 if (n === "Object" && o.constructor) n = o.constructor.name;
33 if (n === "Map" || n === "Set") return Array.from(o);
34 if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
35}
36function _arrayLikeToArray(arr, len) {
37 if (len == null || len > arr.length) len = arr.length;
38 for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
39 return arr2;
40}
41function _createForOfIteratorHelperLoose(o, allowArrayLike) {
42 var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
43 if (it) return (it = it.call(o)).next.bind(it);
44 if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
45 if (it) o = it;
46 var i = 0;
47 return function () {
48 if (i >= o.length) return {
49 done: true
50 };
51 return {
52 done: false,
53 value: o[i++]
54 };
55 };
56 }
57 throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
58}
59
60var hasInitialValue = function hasInitialValue(atom) {
61 return 'init' in atom;
62};
63var isActuallyWritableAtom = function isActuallyWritableAtom(atom) {
64 return !!atom.write;
65};
66var cancelPromiseMap = new WeakMap();
67var registerCancelPromise = function registerCancelPromise(promise, cancel) {
68 cancelPromiseMap.set(promise, cancel);
69 promise.catch(function () {}).finally(function () {
70 return cancelPromiseMap.delete(promise);
71 });
72};
73var cancelPromise = function cancelPromise(promise, next) {
74 var cancel = cancelPromiseMap.get(promise);
75 if (cancel) {
76 cancelPromiseMap.delete(promise);
77 cancel(next);
78 }
79};
80var resolvePromise = function resolvePromise(promise, value) {
81 promise.status = 'fulfilled';
82 promise.value = value;
83};
84var rejectPromise = function rejectPromise(promise, e) {
85 promise.status = 'rejected';
86 promise.reason = e;
87};
88var isPromiseLike = function isPromiseLike(x) {
89 return typeof (x == null ? void 0 : x.then) === 'function';
90};
91var isEqualAtomValue = function isEqualAtomValue(a, b) {
92 return 'v' in a && 'v' in b && Object.is(a.v, b.v);
93};
94var isEqualAtomError = function isEqualAtomError(a, b) {
95 return 'e' in a && 'e' in b && Object.is(a.e, b.e);
96};
97var hasPromiseAtomValue = function hasPromiseAtomValue(a) {
98 return 'v' in a && a.v instanceof Promise;
99};
100var isEqualPromiseAtomValue = function isEqualPromiseAtomValue(a, b) {
101 return 'v' in a && 'v' in b && a.v.orig && a.v.orig === b.v.orig;
102};
103var returnAtomValue = function returnAtomValue(atomState) {
104 if ('e' in atomState) {
105 throw atomState.e;
106 }
107 return atomState.v;
108};
109var createStore = function createStore() {
110 var atomStateMap = new WeakMap();
111 var mountedMap = new WeakMap();
112 var pendingMap = new Map();
113 var storeListenersRev2;
114 var mountedAtoms;
115 if (process.env.NODE_ENV !== 'production') {
116 storeListenersRev2 = new Set();
117 mountedAtoms = new Set();
118 }
119 var getAtomState = function getAtomState(atom) {
120 return atomStateMap.get(atom);
121 };
122 var setAtomState = function setAtomState(atom, atomState) {
123 if (process.env.NODE_ENV !== 'production') {
124 Object.freeze(atomState);
125 }
126 var prevAtomState = atomStateMap.get(atom);
127 atomStateMap.set(atom, atomState);
128 if (!pendingMap.has(atom)) {
129 pendingMap.set(atom, prevAtomState);
130 }
131 if (prevAtomState && hasPromiseAtomValue(prevAtomState)) {
132 var _next = 'v' in atomState ? atomState.v instanceof Promise ? atomState.v : Promise.resolve(atomState.v) : Promise.reject(atomState.e);
133 cancelPromise(prevAtomState.v, _next);
134 }
135 };
136 var updateDependencies = function updateDependencies(atom, nextAtomState, nextDependencies) {
137 var dependencies = new Map();
138 var changed = false;
139 nextDependencies.forEach(function (aState, a) {
140 if (!aState && a === atom) {
141 aState = nextAtomState;
142 }
143 if (aState) {
144 dependencies.set(a, aState);
145 if (nextAtomState.d.get(a) !== aState) {
146 changed = true;
147 }
148 } else if (process.env.NODE_ENV !== 'production') {
149 console.warn('[Bug] atom state not found');
150 }
151 });
152 if (changed || nextAtomState.d.size !== dependencies.size) {
153 nextAtomState.d = dependencies;
154 }
155 };
156 var setAtomValue = function setAtomValue(atom, value, nextDependencies) {
157 var prevAtomState = getAtomState(atom);
158 var nextAtomState = {
159 d: (prevAtomState == null ? void 0 : prevAtomState.d) || new Map(),
160 v: value
161 };
162 if (nextDependencies) {
163 updateDependencies(atom, nextAtomState, nextDependencies);
164 }
165 if (prevAtomState && isEqualAtomValue(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
166 return prevAtomState;
167 }
168 if (prevAtomState && hasPromiseAtomValue(prevAtomState) && hasPromiseAtomValue(nextAtomState) && isEqualPromiseAtomValue(prevAtomState, nextAtomState)) {
169 if (prevAtomState.d === nextAtomState.d) {
170 return prevAtomState;
171 } else {
172 nextAtomState.v = prevAtomState.v;
173 }
174 }
175 setAtomState(atom, nextAtomState);
176 return nextAtomState;
177 };
178 var setAtomValueOrPromise = function setAtomValueOrPromise(atom, valueOrPromise, nextDependencies, abortPromise) {
179 if (isPromiseLike(valueOrPromise)) {
180 var continuePromise;
181 var promise = new Promise(function (resolve, reject) {
182 var settled = false;
183 valueOrPromise.then(function (v) {
184 if (!settled) {
185 settled = true;
186 var prevAtomState = getAtomState(atom);
187 var nextAtomState = setAtomValue(atom, promise, nextDependencies);
188 resolvePromise(promise, v);
189 resolve(v);
190 if (mountedMap.has(atom) && (prevAtomState == null ? void 0 : prevAtomState.d) !== nextAtomState.d) {
191 mountDependencies(atom, nextAtomState, prevAtomState == null ? void 0 : prevAtomState.d);
192 }
193 }
194 }, function (e) {
195 if (!settled) {
196 settled = true;
197 var prevAtomState = getAtomState(atom);
198 var nextAtomState = setAtomValue(atom, promise, nextDependencies);
199 rejectPromise(promise, e);
200 reject(e);
201 if (mountedMap.has(atom) && (prevAtomState == null ? void 0 : prevAtomState.d) !== nextAtomState.d) {
202 mountDependencies(atom, nextAtomState, prevAtomState == null ? void 0 : prevAtomState.d);
203 }
204 }
205 });
206 continuePromise = function continuePromise(next) {
207 if (!settled) {
208 settled = true;
209 next.then(function (v) {
210 return resolvePromise(promise, v);
211 }, function (e) {
212 return rejectPromise(promise, e);
213 });
214 resolve(next);
215 }
216 };
217 });
218 promise.orig = valueOrPromise;
219 promise.status = 'pending';
220 registerCancelPromise(promise, function (next) {
221 if (next) {
222 continuePromise(next);
223 }
224 abortPromise == null || abortPromise();
225 });
226 return setAtomValue(atom, promise, nextDependencies);
227 }
228 return setAtomValue(atom, valueOrPromise, nextDependencies);
229 };
230 var setAtomError = function setAtomError(atom, error, nextDependencies) {
231 var prevAtomState = getAtomState(atom);
232 var nextAtomState = {
233 d: (prevAtomState == null ? void 0 : prevAtomState.d) || new Map(),
234 e: error
235 };
236 if (nextDependencies) {
237 updateDependencies(atom, nextAtomState, nextDependencies);
238 }
239 if (prevAtomState && isEqualAtomError(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
240 return prevAtomState;
241 }
242 setAtomState(atom, nextAtomState);
243 return nextAtomState;
244 };
245 var readAtomState = function readAtomState(atom, force) {
246 var atomState = getAtomState(atom);
247 if (!force && atomState) {
248 if (mountedMap.has(atom)) {
249 return atomState;
250 }
251 if (Array.from(atomState.d).every(function (_ref) {
252 var a = _ref[0],
253 s = _ref[1];
254 return a === atom || readAtomState(a) === s;
255 })) {
256 return atomState;
257 }
258 }
259 var nextDependencies = new Map();
260 var isSync = true;
261 var getter = function getter(a) {
262 if (a === atom) {
263 var _aState = getAtomState(a);
264 if (_aState) {
265 nextDependencies.set(a, _aState);
266 return returnAtomValue(_aState);
267 }
268 if (hasInitialValue(a)) {
269 nextDependencies.set(a, undefined);
270 return a.init;
271 }
272 throw new Error('no atom init');
273 }
274 var aState = readAtomState(a);
275 nextDependencies.set(a, aState);
276 return returnAtomValue(aState);
277 };
278 var controller;
279 var setSelf;
280 var options = {
281 get signal() {
282 if (!controller) {
283 controller = new AbortController();
284 }
285 return controller.signal;
286 },
287 get setSelf() {
288 if (process.env.NODE_ENV !== 'production' && !isActuallyWritableAtom(atom)) {
289 console.warn('setSelf function cannot be used with read-only atom');
290 }
291 if (!setSelf && isActuallyWritableAtom(atom)) {
292 setSelf = function setSelf() {
293 if (process.env.NODE_ENV !== 'production' && isSync) {
294 console.warn('setSelf function cannot be called in sync');
295 }
296 if (!isSync) {
297 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
298 args[_key] = arguments[_key];
299 }
300 return writeAtom.apply(void 0, [atom].concat(args));
301 }
302 };
303 }
304 return setSelf;
305 }
306 };
307 try {
308 var valueOrPromise = atom.read(getter, options);
309 return setAtomValueOrPromise(atom, valueOrPromise, nextDependencies, function () {
310 var _controller;
311 return (_controller = controller) == null ? void 0 : _controller.abort();
312 });
313 } catch (error) {
314 return setAtomError(atom, error, nextDependencies);
315 } finally {
316 isSync = false;
317 }
318 };
319 var readAtom = function readAtom(atom) {
320 return returnAtomValue(readAtomState(atom));
321 };
322 var addAtom = function addAtom(atom) {
323 var mounted = mountedMap.get(atom);
324 if (!mounted) {
325 mounted = mountAtom(atom);
326 }
327 return mounted;
328 };
329 var canUnmountAtom = function canUnmountAtom(atom, mounted) {
330 return !mounted.l.size && (!mounted.t.size || mounted.t.size === 1 && mounted.t.has(atom));
331 };
332 var delAtom = function delAtom(atom) {
333 var mounted = mountedMap.get(atom);
334 if (mounted && canUnmountAtom(atom, mounted)) {
335 unmountAtom(atom);
336 }
337 };
338 var recomputeDependents = function recomputeDependents(atom) {
339 var dependencyMap = new Map();
340 var dirtyMap = new WeakMap();
341 var getDependents = function getDependents(a) {
342 var _mountedMap$get;
343 var dependents = new Set((_mountedMap$get = mountedMap.get(a)) == null ? void 0 : _mountedMap$get.t);
344 pendingMap.forEach(function (_, pendingAtom) {
345 var _getAtomState;
346 if ((_getAtomState = getAtomState(pendingAtom)) != null && _getAtomState.d.has(a)) {
347 dependents.add(pendingAtom);
348 }
349 });
350 return dependents;
351 };
352 var loop1 = function loop1(a) {
353 getDependents(a).forEach(function (dependent) {
354 if (dependent !== a) {
355 dependencyMap.set(dependent, (dependencyMap.get(dependent) || new Set()).add(a));
356 dirtyMap.set(dependent, (dirtyMap.get(dependent) || 0) + 1);
357 loop1(dependent);
358 }
359 });
360 };
361 loop1(atom);
362 var loop2 = function loop2(a) {
363 getDependents(a).forEach(function (dependent) {
364 if (dependent !== a) {
365 var dirtyCount = dirtyMap.get(dependent);
366 if (dirtyCount) {
367 dirtyMap.set(dependent, --dirtyCount);
368 }
369 if (!dirtyCount) {
370 var _dependencyMap$get;
371 var isChanged = !!((_dependencyMap$get = dependencyMap.get(dependent)) != null && _dependencyMap$get.size);
372 if (isChanged) {
373 var prevAtomState = getAtomState(dependent);
374 var nextAtomState = readAtomState(dependent, true);
375 isChanged = !prevAtomState || !isEqualAtomValue(prevAtomState, nextAtomState);
376 }
377 if (!isChanged) {
378 dependencyMap.forEach(function (s) {
379 return s.delete(dependent);
380 });
381 }
382 }
383 loop2(dependent);
384 }
385 });
386 };
387 loop2(atom);
388 };
389 var writeAtomState = function writeAtomState(atom) {
390 var isSync = true;
391 var getter = function getter(a) {
392 return returnAtomValue(readAtomState(a));
393 };
394 var setter = function setter(a) {
395 var r;
396 for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
397 args[_key3 - 1] = arguments[_key3];
398 }
399 if (a === atom) {
400 if (!hasInitialValue(a)) {
401 throw new Error('atom not writable');
402 }
403 var prevAtomState = getAtomState(a);
404 var nextAtomState = setAtomValueOrPromise(a, args[0]);
405 if (!prevAtomState || !isEqualAtomValue(prevAtomState, nextAtomState)) {
406 recomputeDependents(a);
407 }
408 } else {
409 r = writeAtomState.apply(void 0, [a].concat(args));
410 }
411 if (!isSync) {
412 var flushed = flushPending();
413 if (process.env.NODE_ENV !== 'production') {
414 storeListenersRev2.forEach(function (l) {
415 return l({
416 type: 'async-write',
417 flushed: flushed
418 });
419 });
420 }
421 }
422 return r;
423 };
424 for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
425 args[_key2 - 1] = arguments[_key2];
426 }
427 var result = atom.write.apply(atom, [getter, setter].concat(args));
428 isSync = false;
429 return result;
430 };
431 var writeAtom = function writeAtom(atom) {
432 for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
433 args[_key4 - 1] = arguments[_key4];
434 }
435 var result = writeAtomState.apply(void 0, [atom].concat(args));
436 var flushed = flushPending();
437 if (process.env.NODE_ENV !== 'production') {
438 storeListenersRev2.forEach(function (l) {
439 return l({
440 type: 'write',
441 flushed: flushed
442 });
443 });
444 }
445 return result;
446 };
447 var mountAtom = function mountAtom(atom, initialDependent, onMountQueue) {
448 var _getAtomState2;
449 var queue = onMountQueue || [];
450 (_getAtomState2 = getAtomState(atom)) == null || _getAtomState2.d.forEach(function (_, a) {
451 var aMounted = mountedMap.get(a);
452 if (aMounted) {
453 aMounted.t.add(atom);
454 } else {
455 if (a !== atom) {
456 mountAtom(a, atom, queue);
457 }
458 }
459 });
460 readAtomState(atom);
461 var mounted = {
462 t: new Set(initialDependent && [initialDependent]),
463 l: new Set()
464 };
465 mountedMap.set(atom, mounted);
466 if (process.env.NODE_ENV !== 'production') {
467 mountedAtoms.add(atom);
468 }
469 if (isActuallyWritableAtom(atom) && atom.onMount) {
470 var onMount = atom.onMount;
471 queue.push(function () {
472 var onUnmount = onMount(function () {
473 for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
474 args[_key5] = arguments[_key5];
475 }
476 return writeAtom.apply(void 0, [atom].concat(args));
477 });
478 if (onUnmount) {
479 mounted.u = onUnmount;
480 }
481 });
482 }
483 if (!onMountQueue) {
484 queue.forEach(function (f) {
485 return f();
486 });
487 }
488 return mounted;
489 };
490 var unmountAtom = function unmountAtom(atom) {
491 var _mountedMap$get2;
492 var onUnmount = (_mountedMap$get2 = mountedMap.get(atom)) == null ? void 0 : _mountedMap$get2.u;
493 if (onUnmount) {
494 onUnmount();
495 }
496 mountedMap.delete(atom);
497 if (process.env.NODE_ENV !== 'production') {
498 mountedAtoms.delete(atom);
499 }
500 var atomState = getAtomState(atom);
501 if (atomState) {
502 if (hasPromiseAtomValue(atomState)) {
503 cancelPromise(atomState.v);
504 }
505 atomState.d.forEach(function (_, a) {
506 if (a !== atom) {
507 var mounted = mountedMap.get(a);
508 if (mounted) {
509 mounted.t.delete(atom);
510 if (canUnmountAtom(a, mounted)) {
511 unmountAtom(a);
512 }
513 }
514 }
515 });
516 } else if (process.env.NODE_ENV !== 'production') {
517 console.warn('[Bug] could not find atom state to unmount', atom);
518 }
519 };
520 var mountDependencies = function mountDependencies(atom, atomState, prevDependencies) {
521 var depSet = new Set(atomState.d.keys());
522 prevDependencies == null || prevDependencies.forEach(function (_, a) {
523 if (depSet.has(a)) {
524 depSet.delete(a);
525 return;
526 }
527 var mounted = mountedMap.get(a);
528 if (mounted) {
529 mounted.t.delete(atom);
530 if (canUnmountAtom(a, mounted)) {
531 unmountAtom(a);
532 }
533 }
534 });
535 depSet.forEach(function (a) {
536 var mounted = mountedMap.get(a);
537 if (mounted) {
538 mounted.t.add(atom);
539 } else if (mountedMap.has(atom)) {
540 mountAtom(a, atom);
541 }
542 });
543 };
544 var flushPending = function flushPending() {
545 var flushed;
546 if (process.env.NODE_ENV !== 'production') {
547 flushed = new Set();
548 }
549 while (pendingMap.size) {
550 var pending = Array.from(pendingMap);
551 pendingMap.clear();
552 pending.forEach(function (_ref2) {
553 var atom = _ref2[0],
554 prevAtomState = _ref2[1];
555 var atomState = getAtomState(atom);
556 if (atomState) {
557 var mounted = mountedMap.get(atom);
558 if (mounted && atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) {
559 mountDependencies(atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d);
560 }
561 if (mounted && !(prevAtomState && !hasPromiseAtomValue(prevAtomState) && (isEqualAtomValue(prevAtomState, atomState) || isEqualAtomError(prevAtomState, atomState)))) {
562 mounted.l.forEach(function (listener) {
563 return listener();
564 });
565 if (process.env.NODE_ENV !== 'production') {
566 flushed.add(atom);
567 }
568 }
569 } else if (process.env.NODE_ENV !== 'production') {
570 console.warn('[Bug] no atom state to flush');
571 }
572 });
573 }
574 if (process.env.NODE_ENV !== 'production') {
575 return flushed;
576 }
577 };
578 var subscribeAtom = function subscribeAtom(atom, listener) {
579 var mounted = addAtom(atom);
580 var flushed = flushPending();
581 var listeners = mounted.l;
582 listeners.add(listener);
583 if (process.env.NODE_ENV !== 'production') {
584 storeListenersRev2.forEach(function (l) {
585 return l({
586 type: 'sub',
587 flushed: flushed
588 });
589 });
590 }
591 return function () {
592 listeners.delete(listener);
593 delAtom(atom);
594 if (process.env.NODE_ENV !== 'production') {
595 storeListenersRev2.forEach(function (l) {
596 return l({
597 type: 'unsub'
598 });
599 });
600 }
601 };
602 };
603 if (process.env.NODE_ENV !== 'production') {
604 return {
605 get: readAtom,
606 set: writeAtom,
607 sub: subscribeAtom,
608 dev_subscribe_store: function dev_subscribe_store(l, rev) {
609 if (rev !== 2) {
610 throw new Error('The current StoreListener revision is 2.');
611 }
612 storeListenersRev2.add(l);
613 return function () {
614 storeListenersRev2.delete(l);
615 };
616 },
617 dev_get_mounted_atoms: function dev_get_mounted_atoms() {
618 return mountedAtoms.values();
619 },
620 dev_get_atom_state: function dev_get_atom_state(a) {
621 return atomStateMap.get(a);
622 },
623 dev_get_mounted: function dev_get_mounted(a) {
624 return mountedMap.get(a);
625 },
626 dev_restore_atoms: function dev_restore_atoms(values) {
627 for (var _iterator = _createForOfIteratorHelperLoose(values), _step; !(_step = _iterator()).done;) {
628 var _step$value = _step.value,
629 atom = _step$value[0],
630 valueOrPromise = _step$value[1];
631 if (hasInitialValue(atom)) {
632 setAtomValueOrPromise(atom, valueOrPromise);
633 recomputeDependents(atom);
634 }
635 }
636 var flushed = flushPending();
637 storeListenersRev2.forEach(function (l) {
638 return l({
639 type: 'restore',
640 flushed: flushed
641 });
642 });
643 }
644 };
645 }
646 return {
647 get: readAtom,
648 set: writeAtom,
649 sub: subscribeAtom
650 };
651};
652var defaultStore;
653if (process.env.NODE_ENV !== 'production') {
654 if (typeof globalThis.__NUMBER_OF_JOTAI_INSTANCES__ === 'number') {
655 ++globalThis.__NUMBER_OF_JOTAI_INSTANCES__;
656 } else {
657 globalThis.__NUMBER_OF_JOTAI_INSTANCES__ = 1;
658 }
659}
660var getDefaultStore = function getDefaultStore() {
661 if (!defaultStore) {
662 if (process.env.NODE_ENV !== 'production' && globalThis.__NUMBER_OF_JOTAI_INSTANCES__ !== 1) {
663 console.warn('Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044');
664 }
665 defaultStore = createStore();
666 }
667 return defaultStore;
668};
669
670exports.atom = atom;
671exports.createStore = createStore;
672exports.getDefaultStore = getDefaultStore;