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(updatedAtoms) {
339 if (!updatedAtoms.size) {
340 return;
341 }
342 var dependencyMap = new Map();
343 var dirtyMap = new WeakMap();
344 var loop1 = function loop1(a) {
345 var mounted = mountedMap.get(a);
346 mounted == null || mounted.t.forEach(function (dependent) {
347 if (dependent !== a) {
348 dependencyMap.set(dependent, (dependencyMap.get(dependent) || new Set()).add(a));
349 dirtyMap.set(dependent, (dirtyMap.get(dependent) || 0) + 1);
350 loop1(dependent);
351 }
352 });
353 };
354 updatedAtoms.forEach(loop1);
355 var loop2 = function loop2(a) {
356 var mounted = mountedMap.get(a);
357 mounted == null || mounted.t.forEach(function (dependent) {
358 if (dependent !== a) {
359 var dirtyCount = dirtyMap.get(dependent);
360 if (dirtyCount) {
361 dirtyMap.set(dependent, --dirtyCount);
362 }
363 if (!dirtyCount) {
364 var _dependencyMap$get;
365 var isChanged = !!((_dependencyMap$get = dependencyMap.get(dependent)) != null && _dependencyMap$get.size);
366 if (isChanged) {
367 var prevAtomState = getAtomState(dependent);
368 var nextAtomState = readAtomState(dependent, true);
369 isChanged = !prevAtomState || !isEqualAtomValue(prevAtomState, nextAtomState);
370 }
371 if (!isChanged) {
372 dependencyMap.forEach(function (s) {
373 return s.delete(dependent);
374 });
375 }
376 }
377 loop2(dependent);
378 }
379 });
380 };
381 updatedAtoms.forEach(loop2);
382 updatedAtoms.clear();
383 };
384 var writeAtomState = function writeAtomState(updatedAtoms, atom) {
385 var isSync = true;
386 var getter = function getter(a) {
387 return returnAtomValue(readAtomState(a));
388 };
389 var setter = function setter(a) {
390 var r;
391 for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
392 args[_key3 - 1] = arguments[_key3];
393 }
394 if (a === atom) {
395 if (!hasInitialValue(a)) {
396 throw new Error('atom not writable');
397 }
398 var prevAtomState = getAtomState(a);
399 var nextAtomState = setAtomValueOrPromise(a, args[0]);
400 if (!prevAtomState || !isEqualAtomValue(prevAtomState, nextAtomState)) {
401 updatedAtoms.add(a);
402 }
403 } else {
404 r = writeAtomState.apply(void 0, [updatedAtoms, a].concat(args));
405 }
406 if (!isSync) {
407 recomputeDependents(updatedAtoms);
408 var flushed = flushPending();
409 if (process.env.NODE_ENV !== 'production') {
410 storeListenersRev2.forEach(function (l) {
411 return l({
412 type: 'async-write',
413 flushed: flushed
414 });
415 });
416 }
417 }
418 return r;
419 };
420 for (var _len2 = arguments.length, args = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
421 args[_key2 - 2] = arguments[_key2];
422 }
423 var result = atom.write.apply(atom, [getter, setter].concat(args));
424 isSync = false;
425 return result;
426 };
427 var writeAtom = function writeAtom(atom) {
428 var updatedAtoms = new Set();
429 for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
430 args[_key4 - 1] = arguments[_key4];
431 }
432 var result = writeAtomState.apply(void 0, [updatedAtoms, atom].concat(args));
433 recomputeDependents(updatedAtoms);
434 var flushed = flushPending();
435 if (process.env.NODE_ENV !== 'production') {
436 storeListenersRev2.forEach(function (l) {
437 return l({
438 type: 'write',
439 flushed: flushed
440 });
441 });
442 }
443 return result;
444 };
445 var mountAtom = function mountAtom(atom, initialDependent, onMountQueue) {
446 var _getAtomState;
447 var queue = onMountQueue || [];
448 (_getAtomState = getAtomState(atom)) == null || _getAtomState.d.forEach(function (_, a) {
449 var aMounted = mountedMap.get(a);
450 if (aMounted) {
451 aMounted.t.add(atom);
452 } else {
453 if (a !== atom) {
454 mountAtom(a, atom, queue);
455 }
456 }
457 });
458 readAtomState(atom);
459 var mounted = {
460 t: new Set(initialDependent && [initialDependent]),
461 l: new Set()
462 };
463 mountedMap.set(atom, mounted);
464 if (process.env.NODE_ENV !== 'production') {
465 mountedAtoms.add(atom);
466 }
467 if (isActuallyWritableAtom(atom) && atom.onMount) {
468 var onMount = atom.onMount;
469 queue.push(function () {
470 var onUnmount = onMount(function () {
471 for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
472 args[_key5] = arguments[_key5];
473 }
474 return writeAtom.apply(void 0, [atom].concat(args));
475 });
476 if (onUnmount) {
477 mounted.u = onUnmount;
478 }
479 });
480 }
481 if (!onMountQueue) {
482 queue.forEach(function (f) {
483 return f();
484 });
485 }
486 return mounted;
487 };
488 var unmountAtom = function unmountAtom(atom) {
489 var _mountedMap$get;
490 var onUnmount = (_mountedMap$get = mountedMap.get(atom)) == null ? void 0 : _mountedMap$get.u;
491 if (onUnmount) {
492 onUnmount();
493 }
494 mountedMap.delete(atom);
495 if (process.env.NODE_ENV !== 'production') {
496 mountedAtoms.delete(atom);
497 }
498 var atomState = getAtomState(atom);
499 if (atomState) {
500 if (hasPromiseAtomValue(atomState)) {
501 cancelPromise(atomState.v);
502 }
503 atomState.d.forEach(function (_, a) {
504 if (a !== atom) {
505 var mounted = mountedMap.get(a);
506 if (mounted) {
507 mounted.t.delete(atom);
508 if (canUnmountAtom(a, mounted)) {
509 unmountAtom(a);
510 }
511 }
512 }
513 });
514 } else if (process.env.NODE_ENV !== 'production') {
515 console.warn('[Bug] could not find atom state to unmount', atom);
516 }
517 };
518 var mountDependencies = function mountDependencies(atom, atomState, prevDependencies) {
519 var depSet = new Set(atomState.d.keys());
520 prevDependencies == null || prevDependencies.forEach(function (_, a) {
521 if (depSet.has(a)) {
522 depSet.delete(a);
523 return;
524 }
525 var mounted = mountedMap.get(a);
526 if (mounted) {
527 mounted.t.delete(atom);
528 if (canUnmountAtom(a, mounted)) {
529 unmountAtom(a);
530 }
531 }
532 });
533 depSet.forEach(function (a) {
534 var mounted = mountedMap.get(a);
535 if (mounted) {
536 mounted.t.add(atom);
537 } else if (mountedMap.has(atom)) {
538 mountAtom(a, atom);
539 }
540 });
541 };
542 var flushPending = function flushPending() {
543 var flushed;
544 if (process.env.NODE_ENV !== 'production') {
545 flushed = new Set();
546 }
547 while (pendingMap.size) {
548 var pending = Array.from(pendingMap);
549 pendingMap.clear();
550 pending.forEach(function (_ref2) {
551 var atom = _ref2[0],
552 prevAtomState = _ref2[1];
553 var atomState = getAtomState(atom);
554 if (atomState) {
555 var mounted = mountedMap.get(atom);
556 if (mounted && atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) {
557 mountDependencies(atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d);
558 }
559 if (mounted && !(prevAtomState && !hasPromiseAtomValue(prevAtomState) && (isEqualAtomValue(prevAtomState, atomState) || isEqualAtomError(prevAtomState, atomState)))) {
560 mounted.l.forEach(function (listener) {
561 return listener();
562 });
563 if (process.env.NODE_ENV !== 'production') {
564 flushed.add(atom);
565 }
566 }
567 } else if (process.env.NODE_ENV !== 'production') {
568 console.warn('[Bug] no atom state to flush');
569 }
570 });
571 }
572 if (process.env.NODE_ENV !== 'production') {
573 return flushed;
574 }
575 };
576 var subscribeAtom = function subscribeAtom(atom, listener) {
577 var mounted = addAtom(atom);
578 var flushed = flushPending();
579 var listeners = mounted.l;
580 listeners.add(listener);
581 if (process.env.NODE_ENV !== 'production') {
582 storeListenersRev2.forEach(function (l) {
583 return l({
584 type: 'sub',
585 flushed: flushed
586 });
587 });
588 }
589 return function () {
590 listeners.delete(listener);
591 delAtom(atom);
592 if (process.env.NODE_ENV !== 'production') {
593 storeListenersRev2.forEach(function (l) {
594 return l({
595 type: 'unsub'
596 });
597 });
598 }
599 };
600 };
601 if (process.env.NODE_ENV !== 'production') {
602 return {
603 get: readAtom,
604 set: writeAtom,
605 sub: subscribeAtom,
606 dev_subscribe_store: function dev_subscribe_store(l, rev) {
607 if (rev !== 2) {
608 throw new Error('The current StoreListener revision is 2.');
609 }
610 storeListenersRev2.add(l);
611 return function () {
612 storeListenersRev2.delete(l);
613 };
614 },
615 dev_get_mounted_atoms: function dev_get_mounted_atoms() {
616 return mountedAtoms.values();
617 },
618 dev_get_atom_state: function dev_get_atom_state(a) {
619 return atomStateMap.get(a);
620 },
621 dev_get_mounted: function dev_get_mounted(a) {
622 return mountedMap.get(a);
623 },
624 dev_restore_atoms: function dev_restore_atoms(values) {
625 var updatedAtoms = new Set();
626 for (var _iterator = _createForOfIteratorHelperLoose(values), _step; !(_step = _iterator()).done;) {
627 var _step$value = _step.value,
628 atom = _step$value[0],
629 valueOrPromise = _step$value[1];
630 if (hasInitialValue(atom)) {
631 setAtomValueOrPromise(atom, valueOrPromise);
632 updatedAtoms.add(atom);
633 }
634 }
635 recomputeDependents(updatedAtoms);
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;