UNPKG

17.3 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 isEqualAtomValue = function isEqualAtomValue(a, b) {
89 return 'v' in a && 'v' in b && Object.is(a.v, b.v);
90};
91var isEqualAtomError = function isEqualAtomError(a, b) {
92 return 'e' in a && 'e' in b && Object.is(a.e, b.e);
93};
94var hasPromiseAtomValue = function hasPromiseAtomValue(a) {
95 return 'v' in a && a.v instanceof Promise;
96};
97var returnAtomValue = function returnAtomValue(atomState) {
98 if ('e' in atomState) {
99 throw atomState.e;
100 }
101 return atomState.v;
102};
103var createStore = function createStore() {
104 var atomStateMap = new WeakMap();
105 var mountedMap = new WeakMap();
106 var pendingMap = new Map();
107 var stateListeners;
108 var mountedAtoms;
109 if (process.env.NODE_ENV !== "production") {
110 stateListeners = new Set();
111 mountedAtoms = new Set();
112 }
113 var getAtomState = function getAtomState(atom) {
114 return atomStateMap.get(atom);
115 };
116 var setAtomState = function setAtomState(atom, atomState) {
117 if (process.env.NODE_ENV !== "production") {
118 Object.freeze(atomState);
119 }
120 var prevAtomState = atomStateMap.get(atom);
121 atomStateMap.set(atom, atomState);
122 if (!pendingMap.has(atom)) {
123 pendingMap.set(atom, prevAtomState);
124 }
125 if (prevAtomState && hasPromiseAtomValue(prevAtomState)) {
126 var _next = 'v' in atomState ? atomState.v instanceof Promise ? atomState.v : Promise.resolve(atomState.v) : Promise.reject(atomState.e);
127 cancelPromise(prevAtomState.v, _next);
128 }
129 };
130 var updateDependencies = function updateDependencies(atom, nextAtomState, depSet) {
131 var dependencies = new Map();
132 var changed = false;
133 depSet.forEach(function (a) {
134 var aState = a === atom ? nextAtomState : getAtomState(a);
135 if (aState) {
136 dependencies.set(a, aState);
137 if (nextAtomState.d.get(a) !== aState) {
138 changed = true;
139 }
140 } else if (process.env.NODE_ENV !== "production") {
141 console.warn('[Bug] atom state not found');
142 }
143 });
144 if (changed || nextAtomState.d.size !== dependencies.size) {
145 nextAtomState.d = dependencies;
146 }
147 };
148 var setAtomValue = function setAtomValue(atom, value, depSet) {
149 var prevAtomState = getAtomState(atom);
150 var nextAtomState = {
151 d: (prevAtomState == null ? void 0 : prevAtomState.d) || new Map(),
152 v: value
153 };
154 if (depSet) {
155 updateDependencies(atom, nextAtomState, depSet);
156 }
157 if (prevAtomState && isEqualAtomValue(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
158 return prevAtomState;
159 }
160 setAtomState(atom, nextAtomState);
161 return nextAtomState;
162 };
163 var setAtomError = function setAtomError(atom, error, depSet) {
164 var prevAtomState = getAtomState(atom);
165 var nextAtomState = {
166 d: (prevAtomState == null ? void 0 : prevAtomState.d) || new Map(),
167 e: error
168 };
169 if (depSet) {
170 updateDependencies(atom, nextAtomState, depSet);
171 }
172 if (prevAtomState && isEqualAtomError(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
173 return prevAtomState;
174 }
175 setAtomState(atom, nextAtomState);
176 return nextAtomState;
177 };
178 var readAtomState = function readAtomState(atom) {
179 var atomState = getAtomState(atom);
180 if (atomState) {
181 atomState.d.forEach(function (_, a) {
182 if (a !== atom && !mountedMap.has(a)) {
183 readAtomState(a);
184 }
185 });
186 if (Array.from(atomState.d).every(function (_ref) {
187 var a = _ref[0],
188 s = _ref[1];
189 return a === atom || getAtomState(a) === s;
190 })) {
191 return atomState;
192 }
193 }
194 var depSet = new Set();
195 var isSync = true;
196 var getter = function getter(a) {
197 depSet.add(a);
198 if (a === atom) {
199 var _aState = getAtomState(a);
200 if (_aState) {
201 return returnAtomValue(_aState);
202 }
203 if (hasInitialValue(a)) {
204 return a.init;
205 }
206 throw new Error('no atom init');
207 }
208 var aState = readAtomState(a);
209 return returnAtomValue(aState);
210 };
211 var controller;
212 var setSelf;
213 var options = {
214 get signal() {
215 if (!controller) {
216 controller = new AbortController();
217 }
218 return controller.signal;
219 },
220 get setSelf() {
221 if (process.env.NODE_ENV !== "production" && !isActuallyWritableAtom(atom)) {
222 console.warn('setSelf function cannot be used with read-only atom');
223 }
224 if (!setSelf && isActuallyWritableAtom(atom)) {
225 setSelf = function setSelf() {
226 if (process.env.NODE_ENV !== "production" && isSync) {
227 console.warn('setSelf function cannot be called in sync');
228 }
229 if (!isSync) {
230 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
231 args[_key] = arguments[_key];
232 }
233 return writeAtom.apply(void 0, [atom].concat(args));
234 }
235 };
236 }
237 return setSelf;
238 }
239 };
240 try {
241 var value = atom.read(getter, options);
242 if (value instanceof Promise) {
243 var continuePromise;
244 var promise = new Promise(function (resolve, reject) {
245 var settled = false;
246 value.then(function (v) {
247 if (!settled) {
248 resolvePromise(promise, v);
249 resolve(v);
250 }
251 }, function (e) {
252 if (!settled) {
253 rejectPromise(promise, e);
254 reject(e);
255 }
256 }).finally(function () {
257 if (!settled) {
258 settled = true;
259 setAtomValue(atom, promise, depSet);
260 }
261 });
262 continuePromise = function continuePromise(next) {
263 if (!settled) {
264 settled = true;
265 next.then(function (v) {
266 return resolvePromise(promise, v);
267 }, function (e) {
268 return rejectPromise(promise, e);
269 });
270 resolve(next);
271 }
272 };
273 });
274 promise.status = 'pending';
275 registerCancelPromise(promise, function (next) {
276 var _controller;
277 if (next) {
278 continuePromise(next);
279 }
280 (_controller = controller) == null ? void 0 : _controller.abort();
281 });
282 return setAtomValue(atom, promise, depSet);
283 }
284 return setAtomValue(atom, value, depSet);
285 } catch (error) {
286 return setAtomError(atom, error, depSet);
287 } finally {
288 isSync = false;
289 }
290 };
291 var readAtom = function readAtom(atom) {
292 return returnAtomValue(readAtomState(atom));
293 };
294 var addAtom = function addAtom(atom) {
295 var mounted = mountedMap.get(atom);
296 if (!mounted) {
297 mounted = mountAtom(atom);
298 }
299 return mounted;
300 };
301 var canUnmountAtom = function canUnmountAtom(atom, mounted) {
302 return !mounted.l.size && (!mounted.t.size || mounted.t.size === 1 && mounted.t.has(atom));
303 };
304 var delAtom = function delAtom(atom) {
305 var mounted = mountedMap.get(atom);
306 if (mounted && canUnmountAtom(atom, mounted)) {
307 unmountAtom(atom);
308 }
309 };
310 var recomputeDependents = function recomputeDependents(atom) {
311 var mounted = mountedMap.get(atom);
312 mounted == null ? void 0 : mounted.t.forEach(function (dependent) {
313 if (dependent !== atom) {
314 var prevAtomState = getAtomState(dependent);
315 var nextAtomState = readAtomState(dependent);
316 if (!prevAtomState || !isEqualAtomValue(prevAtomState, nextAtomState)) {
317 recomputeDependents(dependent);
318 }
319 }
320 });
321 };
322 var writeAtomState = function writeAtomState(atom) {
323 var isSync = true;
324 var getter = function getter(a) {
325 return returnAtomValue(readAtomState(a));
326 };
327 var setter = function setter(a) {
328 var r;
329 for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
330 args[_key3 - 1] = arguments[_key3];
331 }
332 if (a === atom) {
333 if (!hasInitialValue(a)) {
334 throw new Error('atom not writable');
335 }
336 var prevAtomState = getAtomState(a);
337 var nextAtomState = setAtomValue(a, args[0]);
338 if (!prevAtomState || !isEqualAtomValue(prevAtomState, nextAtomState)) {
339 recomputeDependents(a);
340 }
341 } else {
342 r = writeAtomState.apply(void 0, [a].concat(args));
343 }
344 if (!isSync) {
345 flushPending();
346 }
347 return r;
348 };
349 for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
350 args[_key2 - 1] = arguments[_key2];
351 }
352 var result = atom.write.apply(atom, [getter, setter].concat(args));
353 isSync = false;
354 return result;
355 };
356 var writeAtom = function writeAtom(atom) {
357 for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
358 args[_key4 - 1] = arguments[_key4];
359 }
360 var result = writeAtomState.apply(void 0, [atom].concat(args));
361 flushPending();
362 return result;
363 };
364 var mountAtom = function mountAtom(atom, initialDependent) {
365 var mounted = {
366 t: new Set(initialDependent && [initialDependent]),
367 l: new Set()
368 };
369 mountedMap.set(atom, mounted);
370 if (process.env.NODE_ENV !== "production") {
371 mountedAtoms.add(atom);
372 }
373 readAtomState(atom).d.forEach(function (_, a) {
374 var aMounted = mountedMap.get(a);
375 if (aMounted) {
376 aMounted.t.add(atom);
377 } else {
378 if (a !== atom) {
379 mountAtom(a, atom);
380 }
381 }
382 });
383 readAtomState(atom);
384 if (isActuallyWritableAtom(atom) && atom.onMount) {
385 var onUnmount = atom.onMount(function () {
386 for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
387 args[_key5] = arguments[_key5];
388 }
389 return writeAtom.apply(void 0, [atom].concat(args));
390 });
391 if (onUnmount) {
392 mounted.u = onUnmount;
393 }
394 }
395 return mounted;
396 };
397 var unmountAtom = function unmountAtom(atom) {
398 var _mountedMap$get;
399 var onUnmount = (_mountedMap$get = mountedMap.get(atom)) == null ? void 0 : _mountedMap$get.u;
400 if (onUnmount) {
401 onUnmount();
402 }
403 mountedMap.delete(atom);
404 if (process.env.NODE_ENV !== "production") {
405 mountedAtoms.delete(atom);
406 }
407 var atomState = getAtomState(atom);
408 if (atomState) {
409 if (hasPromiseAtomValue(atomState)) {
410 cancelPromise(atomState.v);
411 }
412 atomState.d.forEach(function (_, a) {
413 if (a !== atom) {
414 var mounted = mountedMap.get(a);
415 if (mounted) {
416 mounted.t.delete(atom);
417 if (canUnmountAtom(a, mounted)) {
418 unmountAtom(a);
419 }
420 }
421 }
422 });
423 } else if (process.env.NODE_ENV !== "production") {
424 console.warn('[Bug] could not find atom state to unmount', atom);
425 }
426 };
427 var mountDependencies = function mountDependencies(atom, atomState, prevDependencies) {
428 var depSet = new Set(atomState.d.keys());
429 prevDependencies == null ? void 0 : prevDependencies.forEach(function (_, a) {
430 if (depSet.has(a)) {
431 depSet.delete(a);
432 return;
433 }
434 var mounted = mountedMap.get(a);
435 if (mounted) {
436 mounted.t.delete(atom);
437 if (canUnmountAtom(a, mounted)) {
438 unmountAtom(a);
439 }
440 }
441 });
442 depSet.forEach(function (a) {
443 var mounted = mountedMap.get(a);
444 if (mounted) {
445 mounted.t.add(atom);
446 } else if (mountedMap.has(atom)) {
447 mountAtom(a, atom);
448 }
449 });
450 };
451 var flushPending = function flushPending() {
452 while (pendingMap.size) {
453 var pending = Array.from(pendingMap);
454 pendingMap.clear();
455 pending.forEach(function (_ref2) {
456 var atom = _ref2[0],
457 prevAtomState = _ref2[1];
458 var atomState = getAtomState(atom);
459 if (atomState) {
460 if (atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) {
461 mountDependencies(atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d);
462 }
463 var mounted = mountedMap.get(atom);
464 if (mounted && !(prevAtomState && !hasPromiseAtomValue(prevAtomState) && (isEqualAtomValue(prevAtomState, atomState) || isEqualAtomError(prevAtomState, atomState)))) {
465 mounted.l.forEach(function (listener) {
466 return listener();
467 });
468 }
469 } else if (process.env.NODE_ENV !== "production") {
470 console.warn('[Bug] no atom state to flush');
471 }
472 });
473 }
474 if (process.env.NODE_ENV !== "production") {
475 stateListeners.forEach(function (l) {
476 return l();
477 });
478 }
479 };
480 var subscribeAtom = function subscribeAtom(atom, listener) {
481 var mounted = addAtom(atom);
482 flushPending();
483 var listeners = mounted.l;
484 listeners.add(listener);
485 return function () {
486 listeners.delete(listener);
487 delAtom(atom);
488 };
489 };
490 if (process.env.NODE_ENV !== "production") {
491 return {
492 get: readAtom,
493 set: writeAtom,
494 sub: subscribeAtom,
495 dev_subscribe_state: function dev_subscribe_state(l) {
496 stateListeners.add(l);
497 return function () {
498 stateListeners.delete(l);
499 };
500 },
501 dev_get_mounted_atoms: function dev_get_mounted_atoms() {
502 return mountedAtoms.values();
503 },
504 dev_get_atom_state: function dev_get_atom_state(a) {
505 return atomStateMap.get(a);
506 },
507 dev_get_mounted: function dev_get_mounted(a) {
508 return mountedMap.get(a);
509 },
510 dev_restore_atoms: function dev_restore_atoms(values) {
511 for (var _iterator = _createForOfIteratorHelperLoose(values), _step; !(_step = _iterator()).done;) {
512 var _step$value = _step.value,
513 atom = _step$value[0],
514 value = _step$value[1];
515 if (hasInitialValue(atom)) {
516 setAtomValue(atom, value);
517 recomputeDependents(atom);
518 }
519 }
520 flushPending();
521 }
522 };
523 }
524 return {
525 get: readAtom,
526 set: writeAtom,
527 sub: subscribeAtom
528 };
529};
530var defaultStore;
531var getDefaultStore = function getDefaultStore() {
532 if (!defaultStore) {
533 defaultStore = createStore();
534 }
535 return defaultStore;
536};
537
538exports.atom = atom;
539exports.createStore = createStore;
540exports.getDefaultStore = getDefaultStore;