UNPKG

21.8 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 storeListenersRev1;
114 var storeListenersRev2;
115 var mountedAtoms;
116 if (process.env.NODE_ENV !== 'production') {
117 storeListenersRev1 = new Set();
118 storeListenersRev2 = new Set();
119 mountedAtoms = new Set();
120 }
121 var getAtomState = function getAtomState(atom) {
122 return atomStateMap.get(atom);
123 };
124 var setAtomState = function setAtomState(atom, atomState) {
125 if (process.env.NODE_ENV !== 'production') {
126 Object.freeze(atomState);
127 }
128 var prevAtomState = atomStateMap.get(atom);
129 atomStateMap.set(atom, atomState);
130 if (!pendingMap.has(atom)) {
131 pendingMap.set(atom, prevAtomState);
132 }
133 if (prevAtomState && hasPromiseAtomValue(prevAtomState)) {
134 var _next = 'v' in atomState ? atomState.v instanceof Promise ? atomState.v : Promise.resolve(atomState.v) : Promise.reject(atomState.e);
135 cancelPromise(prevAtomState.v, _next);
136 }
137 };
138 var updateDependencies = function updateDependencies(atom, nextAtomState, nextDependencies) {
139 var dependencies = new Map();
140 var changed = false;
141 nextDependencies.forEach(function (aState, a) {
142 if (!aState && a === atom) {
143 aState = nextAtomState;
144 }
145 if (aState) {
146 dependencies.set(a, aState);
147 if (nextAtomState.d.get(a) !== aState) {
148 changed = true;
149 }
150 } else if (process.env.NODE_ENV !== 'production') {
151 console.warn('[Bug] atom state not found');
152 }
153 });
154 if (changed || nextAtomState.d.size !== dependencies.size) {
155 nextAtomState.d = dependencies;
156 }
157 };
158 var setAtomValue = function setAtomValue(atom, value, nextDependencies) {
159 var prevAtomState = getAtomState(atom);
160 var nextAtomState = {
161 d: (prevAtomState == null ? void 0 : prevAtomState.d) || new Map(),
162 v: value
163 };
164 if (nextDependencies) {
165 updateDependencies(atom, nextAtomState, nextDependencies);
166 }
167 if (prevAtomState && isEqualAtomValue(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
168 return prevAtomState;
169 }
170 if (prevAtomState && hasPromiseAtomValue(prevAtomState) && hasPromiseAtomValue(nextAtomState) && isEqualPromiseAtomValue(prevAtomState, nextAtomState)) {
171 if (prevAtomState.d === nextAtomState.d) {
172 return prevAtomState;
173 } else {
174 nextAtomState.v = prevAtomState.v;
175 }
176 }
177 setAtomState(atom, nextAtomState);
178 return nextAtomState;
179 };
180 var setAtomValueOrPromise = function setAtomValueOrPromise(atom, valueOrPromise, nextDependencies, abortPromise) {
181 if (isPromiseLike(valueOrPromise)) {
182 var continuePromise;
183 var promise = new Promise(function (resolve, reject) {
184 var settled = false;
185 valueOrPromise.then(function (v) {
186 if (!settled) {
187 settled = true;
188 var prevAtomState = getAtomState(atom);
189 var nextAtomState = setAtomValue(atom, promise, nextDependencies);
190 resolvePromise(promise, v);
191 resolve(v);
192 if ((prevAtomState == null ? void 0 : prevAtomState.d) !== nextAtomState.d) {
193 mountDependencies(atom, nextAtomState, prevAtomState == null ? void 0 : prevAtomState.d);
194 }
195 }
196 }, function (e) {
197 if (!settled) {
198 settled = true;
199 var prevAtomState = getAtomState(atom);
200 var nextAtomState = setAtomValue(atom, promise, nextDependencies);
201 rejectPromise(promise, e);
202 reject(e);
203 if ((prevAtomState == null ? void 0 : prevAtomState.d) !== nextAtomState.d) {
204 mountDependencies(atom, nextAtomState, prevAtomState == null ? void 0 : prevAtomState.d);
205 }
206 }
207 });
208 continuePromise = function continuePromise(next) {
209 if (!settled) {
210 settled = true;
211 next.then(function (v) {
212 return resolvePromise(promise, v);
213 }, function (e) {
214 return rejectPromise(promise, e);
215 });
216 resolve(next);
217 }
218 };
219 });
220 promise.orig = valueOrPromise;
221 promise.status = 'pending';
222 registerCancelPromise(promise, function (next) {
223 if (next) {
224 continuePromise(next);
225 }
226 abortPromise == null ? void 0 : abortPromise();
227 });
228 return setAtomValue(atom, promise, nextDependencies);
229 }
230 return setAtomValue(atom, valueOrPromise, nextDependencies);
231 };
232 var setAtomError = function setAtomError(atom, error, nextDependencies) {
233 var prevAtomState = getAtomState(atom);
234 var nextAtomState = {
235 d: (prevAtomState == null ? void 0 : prevAtomState.d) || new Map(),
236 e: error
237 };
238 if (nextDependencies) {
239 updateDependencies(atom, nextAtomState, nextDependencies);
240 }
241 if (prevAtomState && isEqualAtomError(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
242 return prevAtomState;
243 }
244 setAtomState(atom, nextAtomState);
245 return nextAtomState;
246 };
247 var readAtomState = function readAtomState(atom) {
248 var atomState = getAtomState(atom);
249 if (atomState) {
250 atomState.d.forEach(function (_, a) {
251 if (a !== atom && !mountedMap.has(a)) {
252 readAtomState(a);
253 }
254 });
255 if (Array.from(atomState.d).every(function (_ref) {
256 var a = _ref[0],
257 s = _ref[1];
258 return a === atom || getAtomState(a) === s;
259 })) {
260 return atomState;
261 }
262 }
263 var nextDependencies = new Map();
264 var isSync = true;
265 var getter = function getter(a) {
266 if (a === atom) {
267 var _aState = getAtomState(a);
268 if (_aState) {
269 nextDependencies.set(a, _aState);
270 return returnAtomValue(_aState);
271 }
272 if (hasInitialValue(a)) {
273 nextDependencies.set(a, undefined);
274 return a.init;
275 }
276 throw new Error('no atom init');
277 }
278 var aState = readAtomState(a);
279 nextDependencies.set(a, aState);
280 return returnAtomValue(aState);
281 };
282 var controller;
283 var setSelf;
284 var options = {
285 get signal() {
286 if (!controller) {
287 controller = new AbortController();
288 }
289 return controller.signal;
290 },
291 get setSelf() {
292 if (process.env.NODE_ENV !== 'production' && !isActuallyWritableAtom(atom)) {
293 console.warn('setSelf function cannot be used with read-only atom');
294 }
295 if (!setSelf && isActuallyWritableAtom(atom)) {
296 setSelf = function setSelf() {
297 if (process.env.NODE_ENV !== 'production' && isSync) {
298 console.warn('setSelf function cannot be called in sync');
299 }
300 if (!isSync) {
301 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
302 args[_key] = arguments[_key];
303 }
304 return writeAtom.apply(void 0, [atom].concat(args));
305 }
306 };
307 }
308 return setSelf;
309 }
310 };
311 try {
312 var valueOrPromise = atom.read(getter, options);
313 return setAtomValueOrPromise(atom, valueOrPromise, nextDependencies, function () {
314 var _controller;
315 return (_controller = controller) == null ? void 0 : _controller.abort();
316 });
317 } catch (error) {
318 return setAtomError(atom, error, nextDependencies);
319 } finally {
320 isSync = false;
321 }
322 };
323 var readAtom = function readAtom(atom) {
324 return returnAtomValue(readAtomState(atom));
325 };
326 var addAtom = function addAtom(atom) {
327 var mounted = mountedMap.get(atom);
328 if (!mounted) {
329 mounted = mountAtom(atom);
330 }
331 return mounted;
332 };
333 var canUnmountAtom = function canUnmountAtom(atom, mounted) {
334 return !mounted.l.size && (!mounted.t.size || mounted.t.size === 1 && mounted.t.has(atom));
335 };
336 var delAtom = function delAtom(atom) {
337 var mounted = mountedMap.get(atom);
338 if (mounted && canUnmountAtom(atom, mounted)) {
339 unmountAtom(atom);
340 }
341 };
342 var recomputeDependents = function recomputeDependents(atom) {
343 var dependencyMap = new Map();
344 var dirtyMap = new WeakMap();
345 var loop1 = function loop1(a) {
346 var mounted = mountedMap.get(a);
347 mounted == null ? void 0 : mounted.t.forEach(function (dependent) {
348 if (dependent !== a) {
349 dependencyMap.set(dependent, (dependencyMap.get(dependent) || new Set()).add(a));
350 dirtyMap.set(dependent, (dirtyMap.get(dependent) || 0) + 1);
351 loop1(dependent);
352 }
353 });
354 };
355 loop1(atom);
356 var loop2 = function loop2(a) {
357 var mounted = mountedMap.get(a);
358 mounted == null ? void 0 : mounted.t.forEach(function (dependent) {
359 if (dependent !== a) {
360 var dirtyCount = dirtyMap.get(dependent);
361 if (dirtyCount) {
362 dirtyMap.set(dependent, --dirtyCount);
363 }
364 if (!dirtyCount) {
365 var _dependencyMap$get;
366 var isChanged = !!((_dependencyMap$get = dependencyMap.get(dependent)) != null && _dependencyMap$get.size);
367 if (isChanged) {
368 var prevAtomState = getAtomState(dependent);
369 var nextAtomState = readAtomState(dependent);
370 isChanged = !prevAtomState || !isEqualAtomValue(prevAtomState, nextAtomState);
371 }
372 if (!isChanged) {
373 dependencyMap.forEach(function (s) {
374 return s.delete(dependent);
375 });
376 }
377 }
378 loop2(dependent);
379 }
380 });
381 };
382 loop2(atom);
383 };
384 var writeAtomState = function writeAtomState(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 recomputeDependents(a);
402 }
403 } else {
404 r = writeAtomState.apply(void 0, [a].concat(args));
405 }
406 if (!isSync) {
407 var flushed = flushPending();
408 if (process.env.NODE_ENV !== 'production') {
409 storeListenersRev2.forEach(function (l) {
410 return l({
411 type: 'async-write',
412 flushed: flushed
413 });
414 });
415 }
416 }
417 return r;
418 };
419 for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
420 args[_key2 - 1] = arguments[_key2];
421 }
422 var result = atom.write.apply(atom, [getter, setter].concat(args));
423 isSync = false;
424 return result;
425 };
426 var writeAtom = function writeAtom(atom) {
427 for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
428 args[_key4 - 1] = arguments[_key4];
429 }
430 var result = writeAtomState.apply(void 0, [atom].concat(args));
431 var flushed = flushPending();
432 if (process.env.NODE_ENV !== 'production') {
433 storeListenersRev2.forEach(function (l) {
434 return l({
435 type: 'write',
436 flushed: flushed
437 });
438 });
439 }
440 return result;
441 };
442 var mountAtom = function mountAtom(atom, initialDependent) {
443 var mounted = {
444 t: new Set(initialDependent && [initialDependent]),
445 l: new Set()
446 };
447 mountedMap.set(atom, mounted);
448 if (process.env.NODE_ENV !== 'production') {
449 mountedAtoms.add(atom);
450 }
451 readAtomState(atom).d.forEach(function (_, a) {
452 var aMounted = mountedMap.get(a);
453 if (aMounted) {
454 aMounted.t.add(atom);
455 } else {
456 if (a !== atom) {
457 mountAtom(a, atom);
458 }
459 }
460 });
461 readAtomState(atom);
462 if (isActuallyWritableAtom(atom) && atom.onMount) {
463 var onUnmount = atom.onMount(function () {
464 for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
465 args[_key5] = arguments[_key5];
466 }
467 return writeAtom.apply(void 0, [atom].concat(args));
468 });
469 if (onUnmount) {
470 mounted.u = onUnmount;
471 }
472 }
473 return mounted;
474 };
475 var unmountAtom = function unmountAtom(atom) {
476 var _mountedMap$get;
477 var onUnmount = (_mountedMap$get = mountedMap.get(atom)) == null ? void 0 : _mountedMap$get.u;
478 if (onUnmount) {
479 onUnmount();
480 }
481 mountedMap.delete(atom);
482 if (process.env.NODE_ENV !== 'production') {
483 mountedAtoms.delete(atom);
484 }
485 var atomState = getAtomState(atom);
486 if (atomState) {
487 if (hasPromiseAtomValue(atomState)) {
488 cancelPromise(atomState.v);
489 }
490 atomState.d.forEach(function (_, a) {
491 if (a !== atom) {
492 var mounted = mountedMap.get(a);
493 if (mounted) {
494 mounted.t.delete(atom);
495 if (canUnmountAtom(a, mounted)) {
496 unmountAtom(a);
497 }
498 }
499 }
500 });
501 } else if (process.env.NODE_ENV !== 'production') {
502 console.warn('[Bug] could not find atom state to unmount', atom);
503 }
504 };
505 var mountDependencies = function mountDependencies(atom, atomState, prevDependencies) {
506 var depSet = new Set(atomState.d.keys());
507 prevDependencies == null ? void 0 : prevDependencies.forEach(function (_, a) {
508 if (depSet.has(a)) {
509 depSet.delete(a);
510 return;
511 }
512 var mounted = mountedMap.get(a);
513 if (mounted) {
514 mounted.t.delete(atom);
515 if (canUnmountAtom(a, mounted)) {
516 unmountAtom(a);
517 }
518 }
519 });
520 depSet.forEach(function (a) {
521 var mounted = mountedMap.get(a);
522 if (mounted) {
523 mounted.t.add(atom);
524 } else if (mountedMap.has(atom)) {
525 mountAtom(a, atom);
526 }
527 });
528 };
529 var flushPending = function flushPending() {
530 var flushed;
531 if (process.env.NODE_ENV !== 'production') {
532 flushed = new Set();
533 }
534 while (pendingMap.size) {
535 var pending = Array.from(pendingMap);
536 pendingMap.clear();
537 pending.forEach(function (_ref2) {
538 var atom = _ref2[0],
539 prevAtomState = _ref2[1];
540 var atomState = getAtomState(atom);
541 if (atomState) {
542 if (atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) {
543 mountDependencies(atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d);
544 }
545 var mounted = mountedMap.get(atom);
546 if (mounted && !(prevAtomState && !hasPromiseAtomValue(prevAtomState) && (isEqualAtomValue(prevAtomState, atomState) || isEqualAtomError(prevAtomState, atomState)))) {
547 mounted.l.forEach(function (listener) {
548 return listener();
549 });
550 if (process.env.NODE_ENV !== 'production') {
551 flushed.add(atom);
552 }
553 }
554 } else if (process.env.NODE_ENV !== 'production') {
555 console.warn('[Bug] no atom state to flush');
556 }
557 });
558 }
559 if (process.env.NODE_ENV !== 'production') {
560 storeListenersRev1.forEach(function (l) {
561 return l('state');
562 });
563 return flushed;
564 }
565 };
566 var subscribeAtom = function subscribeAtom(atom, listener) {
567 var mounted = addAtom(atom);
568 var flushed = flushPending();
569 var listeners = mounted.l;
570 listeners.add(listener);
571 if (process.env.NODE_ENV !== 'production') {
572 storeListenersRev1.forEach(function (l) {
573 return l('sub');
574 });
575 storeListenersRev2.forEach(function (l) {
576 return l({
577 type: 'sub',
578 flushed: flushed
579 });
580 });
581 }
582 return function () {
583 listeners.delete(listener);
584 delAtom(atom);
585 if (process.env.NODE_ENV !== 'production') {
586 storeListenersRev1.forEach(function (l) {
587 return l('unsub');
588 });
589 storeListenersRev2.forEach(function (l) {
590 return l({
591 type: 'unsub'
592 });
593 });
594 }
595 };
596 };
597 if (process.env.NODE_ENV !== 'production') {
598 return {
599 get: readAtom,
600 set: writeAtom,
601 sub: subscribeAtom,
602 dev_subscribe_store: function (l, rev) {
603 if (rev !== 2) {
604 console.warn('The current StoreListener revision is 2. The older ones are deprecated.');
605 storeListenersRev1.add(l);
606 return function () {
607 storeListenersRev1.delete(l);
608 };
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 for (var _iterator = _createForOfIteratorHelperLoose(values), _step; !(_step = _iterator()).done;) {
626 var _step$value = _step.value,
627 atom = _step$value[0],
628 valueOrPromise = _step$value[1];
629 if (hasInitialValue(atom)) {
630 setAtomValueOrPromise(atom, valueOrPromise);
631 recomputeDependents(atom);
632 }
633 }
634 var flushed = flushPending();
635 storeListenersRev2.forEach(function (l) {
636 return l({
637 type: 'restore',
638 flushed: flushed
639 });
640 });
641 }
642 };
643 }
644 return {
645 get: readAtom,
646 set: writeAtom,
647 sub: subscribeAtom
648 };
649};
650var defaultStore;
651var getDefaultStore = function getDefaultStore() {
652 if (!defaultStore) {
653 defaultStore = createStore();
654 }
655 return defaultStore;
656};
657
658exports.atom = atom;
659exports.createStore = createStore;
660exports.getDefaultStore = getDefaultStore;