1 | (function (global, factory) {
|
2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
3 | typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jotaiExperimental = {}));
|
5 | })(this, (function (exports) { 'use strict';
|
6 |
|
7 | var keyCount = 0;
|
8 | function atom(read, write) {
|
9 | var key = "atom" + ++keyCount;
|
10 | var config = {
|
11 | toString: function toString() {
|
12 | return key;
|
13 | }
|
14 | };
|
15 | if (typeof read === 'function') {
|
16 | config.read = read;
|
17 | } else {
|
18 | config.init = read;
|
19 | config.read = defaultRead;
|
20 | config.write = defaultWrite;
|
21 | }
|
22 | if (write) {
|
23 | config.write = write;
|
24 | }
|
25 | return config;
|
26 | }
|
27 | function defaultRead(get) {
|
28 | return get(this);
|
29 | }
|
30 | function defaultWrite(get, set, arg) {
|
31 | return set(this, typeof arg === 'function' ? arg(get(this)) : arg);
|
32 | }
|
33 |
|
34 | function _unsupportedIterableToArray(o, minLen) {
|
35 | if (!o) return;
|
36 | if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
37 | var n = Object.prototype.toString.call(o).slice(8, -1);
|
38 | if (n === "Object" && o.constructor) n = o.constructor.name;
|
39 | if (n === "Map" || n === "Set") return Array.from(o);
|
40 | if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
41 | }
|
42 | function _arrayLikeToArray(arr, len) {
|
43 | if (len == null || len > arr.length) len = arr.length;
|
44 | for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
45 | return arr2;
|
46 | }
|
47 | function _createForOfIteratorHelperLoose(o, allowArrayLike) {
|
48 | var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
|
49 | if (it) return (it = it.call(o)).next.bind(it);
|
50 | if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
51 | if (it) o = it;
|
52 | var i = 0;
|
53 | return function () {
|
54 | if (i >= o.length) return {
|
55 | done: true
|
56 | };
|
57 | return {
|
58 | done: false,
|
59 | value: o[i++]
|
60 | };
|
61 | };
|
62 | }
|
63 | throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
64 | }
|
65 |
|
66 | var isSelfAtom = function isSelfAtom(atom, a) {
|
67 | return atom.unstable_is ? atom.unstable_is(a) : a === atom;
|
68 | };
|
69 | var hasInitialValue = function hasInitialValue(atom) {
|
70 | return 'init' in atom;
|
71 | };
|
72 | var isActuallyWritableAtom = function isActuallyWritableAtom(atom) {
|
73 | return !!atom.write;
|
74 | };
|
75 | var createPendingPair = function createPendingPair() {
|
76 | return [new Set(), new Set()];
|
77 | };
|
78 | var addPending = function addPending(pendingPair, pending) {
|
79 | (pendingPair[0] || pendingPair[1]).add(pending);
|
80 | };
|
81 | var flushPending = function flushPending(pendingPair, isAsync) {
|
82 | var pendingSet;
|
83 | if (isAsync) {
|
84 | if (pendingPair[0]) {
|
85 | return;
|
86 | }
|
87 | pendingSet = pendingPair[1];
|
88 | } else {
|
89 | if (!pendingPair[0]) {
|
90 | throw new Error('[Bug] cannot sync flush twice');
|
91 | }
|
92 | pendingSet = pendingPair[0];
|
93 | }
|
94 | var flushed = new Set();
|
95 | while (pendingSet.size) {
|
96 | var copy = new Set(pendingSet);
|
97 | pendingSet.clear();
|
98 | copy.forEach(function (pending) {
|
99 | if (typeof pending === 'function') {
|
100 | pending();
|
101 | } else {
|
102 | var _atom = pending[0],
|
103 | atomState = pending[1];
|
104 | if (!flushed.has(_atom) && atomState.m) {
|
105 | atomState.m.l.forEach(function (listener) {
|
106 | return listener();
|
107 | });
|
108 | flushed.add(_atom);
|
109 | }
|
110 | }
|
111 | });
|
112 | }
|
113 | pendingPair[0] = undefined;
|
114 | return flushed;
|
115 | };
|
116 | var CONTINUE_PROMISE = Symbol('CONTINUE_PROMISE' );
|
117 | var PENDING = 'pending';
|
118 | var FULFILLED = 'fulfilled';
|
119 | var REJECTED = 'rejected';
|
120 | var isContinuablePromise = function isContinuablePromise(promise) {
|
121 | return typeof promise === 'object' && promise !== null && CONTINUE_PROMISE in promise;
|
122 | };
|
123 | var continuablePromiseMap = new WeakMap();
|
124 | var createContinuablePromise = function createContinuablePromise(promise, abort, complete) {
|
125 | if (!continuablePromiseMap.has(promise)) {
|
126 | var continuePromise;
|
127 | var p = new Promise(function (resolve, reject) {
|
128 | var curr = promise;
|
129 | var onFullfilled = function onFullfilled(me) {
|
130 | return function (v) {
|
131 | if (curr === me) {
|
132 | p.status = FULFILLED;
|
133 | p.value = v;
|
134 | resolve(v);
|
135 | complete();
|
136 | }
|
137 | };
|
138 | };
|
139 | var onRejected = function onRejected(me) {
|
140 | return function (e) {
|
141 | if (curr === me) {
|
142 | p.status = REJECTED;
|
143 | p.reason = e;
|
144 | reject(e);
|
145 | complete();
|
146 | }
|
147 | };
|
148 | };
|
149 | promise.then(onFullfilled(promise), onRejected(promise));
|
150 | continuePromise = function continuePromise(nextPromise, nextAbort) {
|
151 | if (nextPromise) {
|
152 | continuablePromiseMap.set(nextPromise, p);
|
153 | curr = nextPromise;
|
154 | nextPromise.then(onFullfilled(nextPromise), onRejected(nextPromise));
|
155 | }
|
156 | abort();
|
157 | abort = nextAbort;
|
158 | };
|
159 | });
|
160 | p.status = PENDING;
|
161 | p[CONTINUE_PROMISE] = continuePromise;
|
162 | continuablePromiseMap.set(promise, p);
|
163 | }
|
164 | return continuablePromiseMap.get(promise);
|
165 | };
|
166 | var isPromiseLike = function isPromiseLike(x) {
|
167 | return typeof (x == null ? void 0 : x.then) === 'function';
|
168 | };
|
169 | var getPendingContinuablePromise = function getPendingContinuablePromise(atomState) {
|
170 | var _s;
|
171 | var value = (_s = atomState.s) == null ? void 0 : _s.v;
|
172 | if (isContinuablePromise(value) && value.status === PENDING) {
|
173 | return value;
|
174 | }
|
175 | return null;
|
176 | };
|
177 | var returnAtomValue = function returnAtomValue(atomState) {
|
178 | if ('e' in atomState.s) {
|
179 | throw atomState.s.e;
|
180 | }
|
181 | return atomState.s.v;
|
182 | };
|
183 | var setAtomStateValueOrPromise = function setAtomStateValueOrPromise(atomState, valueOrPromise, abortPromise, completePromise) {
|
184 | if (abortPromise === void 0) {
|
185 | abortPromise = function abortPromise() {};
|
186 | }
|
187 | if (completePromise === void 0) {
|
188 | completePromise = function completePromise() {};
|
189 | }
|
190 | var pendingPromise = getPendingContinuablePromise(atomState);
|
191 | if (isPromiseLike(valueOrPromise)) {
|
192 | if (pendingPromise) {
|
193 | if (pendingPromise !== valueOrPromise) {
|
194 | pendingPromise[CONTINUE_PROMISE](valueOrPromise, abortPromise);
|
195 | }
|
196 | } else {
|
197 | var continuablePromise = createContinuablePromise(valueOrPromise, abortPromise, completePromise);
|
198 | atomState.s = {
|
199 | v: continuablePromise
|
200 | };
|
201 | }
|
202 | } else {
|
203 | if (pendingPromise) {
|
204 | pendingPromise[CONTINUE_PROMISE](Promise.resolve(valueOrPromise), abortPromise);
|
205 | }
|
206 | atomState.s = {
|
207 | v: valueOrPromise
|
208 | };
|
209 | }
|
210 | };
|
211 | var createStore = function createStore() {
|
212 | var atomStateMap = new WeakMap();
|
213 | var getAtomState = function getAtomState(atom) {
|
214 | var atomState = atomStateMap.get(atom);
|
215 | if (!atomState) {
|
216 | atomState = {
|
217 | d: new Map(),
|
218 | t: new Set()
|
219 | };
|
220 | atomStateMap.set(atom, atomState);
|
221 | }
|
222 | return atomState;
|
223 | };
|
224 | var clearDependencies = function clearDependencies(atom) {
|
225 | var atomState = getAtomState(atom);
|
226 | for (var _iterator = _createForOfIteratorHelperLoose(atomState.d.keys()), _step; !(_step = _iterator()).done;) {
|
227 | var a = _step.value;
|
228 | getAtomState(a).t.delete(atom);
|
229 | }
|
230 | atomState.d.clear();
|
231 | };
|
232 | var addDependency = function addDependency(atom, a, aState, isSync) {
|
233 | if (a === atom) {
|
234 | throw new Error('[Bug] atom cannot depend on itself');
|
235 | }
|
236 | var atomState = getAtomState(atom);
|
237 | atomState.d.set(a, aState.s);
|
238 | aState.t.add(atom);
|
239 | if (!isSync && atomState.m) {
|
240 | var pendingPair = createPendingPair();
|
241 | mountDependencies(pendingPair, atomState);
|
242 | flushPending(pendingPair);
|
243 | }
|
244 | };
|
245 | var readAtomState = function readAtomState(atom, force) {
|
246 | var atomState = getAtomState(atom);
|
247 | if (!force && 's' in atomState) {
|
248 | if (atomState.m) {
|
249 | return atomState;
|
250 | }
|
251 | if (Array.from(atomState.d).every(function (_ref) {
|
252 | var a = _ref[0],
|
253 | s = _ref[1];
|
254 | var aState = readAtomState(a);
|
255 | return 'v' in s && 'v' in aState.s && Object.is(s.v, aState.s.v);
|
256 | })) {
|
257 | return atomState;
|
258 | }
|
259 | }
|
260 | clearDependencies(atom);
|
261 | var isSync = true;
|
262 | var getter = function getter(a) {
|
263 | if (isSelfAtom(atom, a)) {
|
264 | var _aState = getAtomState(a);
|
265 | if (!_aState.s) {
|
266 | if (hasInitialValue(a)) {
|
267 | setAtomStateValueOrPromise(_aState, a.init);
|
268 | } else {
|
269 | throw new Error('no atom init');
|
270 | }
|
271 | }
|
272 | return returnAtomValue(_aState);
|
273 | }
|
274 | var aState = readAtomState(a);
|
275 | addDependency(atom, a, aState, isSync);
|
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 (!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 (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 | setAtomStateValueOrPromise(atomState, valueOrPromise, function () {
|
310 | var _controller;
|
311 | return (_controller = controller) == null ? void 0 : _controller.abort();
|
312 | }, function () {
|
313 | if (atomState.m) {
|
314 | var pendingPair = createPendingPair();
|
315 | mountDependencies(pendingPair, atomState);
|
316 | flushPending(pendingPair);
|
317 | }
|
318 | });
|
319 | return atomState;
|
320 | } catch (error) {
|
321 | atomState.s = {
|
322 | e: error
|
323 | };
|
324 | return atomState;
|
325 | } finally {
|
326 | isSync = false;
|
327 | }
|
328 | };
|
329 | var readAtom = function readAtom(atom) {
|
330 | return returnAtomValue(readAtomState(atom));
|
331 | };
|
332 | var recomputeDependents = function recomputeDependents(pendingPair, atom) {
|
333 | var topsortedAtoms = [];
|
334 | var markedAtoms = new Set();
|
335 | var visit = function visit(n) {
|
336 | if (markedAtoms.has(n)) {
|
337 | return;
|
338 | }
|
339 | markedAtoms.add(n);
|
340 | for (var _iterator2 = _createForOfIteratorHelperLoose(getAtomState(n).t), _step2; !(_step2 = _iterator2()).done;) {
|
341 | var m = _step2.value;
|
342 | if (n !== m) {
|
343 | visit(m);
|
344 | }
|
345 | }
|
346 | topsortedAtoms.push(n);
|
347 | };
|
348 | visit(atom);
|
349 | var changedAtoms = new Set([atom]);
|
350 | for (var i = topsortedAtoms.length - 1; i >= 0; --i) {
|
351 | var a = topsortedAtoms[i];
|
352 | var aState = getAtomState(a);
|
353 | var prev = aState.s;
|
354 | var hasChangedDeps = false;
|
355 | for (var _iterator3 = _createForOfIteratorHelperLoose(aState.d.keys()), _step3; !(_step3 = _iterator3()).done;) {
|
356 | var dep = _step3.value;
|
357 | if (dep !== a && changedAtoms.has(dep)) {
|
358 | hasChangedDeps = true;
|
359 | break;
|
360 | }
|
361 | }
|
362 | if (hasChangedDeps) {
|
363 | if (aState.m || getPendingContinuablePromise(aState)) {
|
364 | readAtomState(a, true);
|
365 | mountDependencies(pendingPair, aState);
|
366 | if (!prev || !('v' in prev) || !('v' in aState.s) || !Object.is(prev.v, aState.s.v)) {
|
367 | addPending(pendingPair, [a, aState]);
|
368 | changedAtoms.add(a);
|
369 | }
|
370 | }
|
371 | }
|
372 | }
|
373 | };
|
374 | var writeAtomState = function writeAtomState(pendingPair, atom) {
|
375 | var getter = function getter(a) {
|
376 | return returnAtomValue(readAtomState(a));
|
377 | };
|
378 | var setter = function setter(a) {
|
379 | var r;
|
380 | for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
|
381 | args[_key3 - 1] = arguments[_key3];
|
382 | }
|
383 | if (isSelfAtom(atom, a)) {
|
384 | if (!hasInitialValue(a)) {
|
385 | throw new Error('atom not writable');
|
386 | }
|
387 | var aState = getAtomState(a);
|
388 | var prev = aState.s;
|
389 | var v = args[0];
|
390 | setAtomStateValueOrPromise(aState, v);
|
391 | mountDependencies(pendingPair, aState);
|
392 | var curr = aState.s;
|
393 | if (!prev || !('v' in prev) || !('v' in curr) || !Object.is(prev.v, curr.v)) {
|
394 | addPending(pendingPair, [a, aState]);
|
395 | recomputeDependents(pendingPair, a);
|
396 | }
|
397 | } else {
|
398 | r = writeAtomState.apply(void 0, [pendingPair, a].concat(args));
|
399 | }
|
400 | flushPending(pendingPair, true);
|
401 | return r;
|
402 | };
|
403 | for (var _len2 = arguments.length, args = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
|
404 | args[_key2 - 2] = arguments[_key2];
|
405 | }
|
406 | var result = atom.write.apply(atom, [getter, setter].concat(args));
|
407 | return result;
|
408 | };
|
409 | var writeAtom = function writeAtom(atom) {
|
410 | var pendingPair = createPendingPair();
|
411 | for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
|
412 | args[_key4 - 1] = arguments[_key4];
|
413 | }
|
414 | var result = writeAtomState.apply(void 0, [pendingPair, atom].concat(args));
|
415 | flushPending(pendingPair);
|
416 | return result;
|
417 | };
|
418 | var mountDependencies = function mountDependencies(pendingPair, atomState) {
|
419 | if (atomState.m && !getPendingContinuablePromise(atomState)) {
|
420 | for (var _iterator4 = _createForOfIteratorHelperLoose(atomState.d.keys()), _step4; !(_step4 = _iterator4()).done;) {
|
421 | var a = _step4.value;
|
422 | if (!atomState.m.d.has(a)) {
|
423 | mountAtom(pendingPair, a);
|
424 | atomState.m.d.add(a);
|
425 | }
|
426 | }
|
427 | for (var _iterator5 = _createForOfIteratorHelperLoose(atomState.m.d || []), _step5; !(_step5 = _iterator5()).done;) {
|
428 | var _a = _step5.value;
|
429 | if (!atomState.d.has(_a)) {
|
430 | unmountAtom(pendingPair, _a);
|
431 | atomState.m.d.delete(_a);
|
432 | }
|
433 | }
|
434 | }
|
435 | };
|
436 | var mountAtom = function mountAtom(pendingPair, atom) {
|
437 | var atomState = getAtomState(atom);
|
438 | if (!atomState.m) {
|
439 | readAtomState(atom);
|
440 | for (var _iterator6 = _createForOfIteratorHelperLoose(atomState.d.keys()), _step6; !(_step6 = _iterator6()).done;) {
|
441 | var a = _step6.value;
|
442 | mountAtom(pendingPair, a);
|
443 | }
|
444 | atomState.m = {
|
445 | l: new Set(),
|
446 | d: new Set(atomState.d.keys())
|
447 | };
|
448 | if (isActuallyWritableAtom(atom) && atom.onMount) {
|
449 | var mounted = atomState.m;
|
450 | var onMount = atom.onMount;
|
451 | addPending(pendingPair, function () {
|
452 | var onUnmount = onMount(function () {
|
453 | for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
|
454 | args[_key5] = arguments[_key5];
|
455 | }
|
456 | return writeAtomState.apply(void 0, [pendingPair, atom].concat(args));
|
457 | });
|
458 | if (onUnmount) {
|
459 | mounted.u = onUnmount;
|
460 | }
|
461 | });
|
462 | }
|
463 | }
|
464 | return atomState.m;
|
465 | };
|
466 | var unmountAtom = function unmountAtom(pendingPair, atom) {
|
467 | var atomState = getAtomState(atom);
|
468 | if (atomState.m && !atomState.m.l.size && !Array.from(atomState.t).some(function (a) {
|
469 | return getAtomState(a).m;
|
470 | })) {
|
471 | var onUnmount = atomState.m.u;
|
472 | if (onUnmount) {
|
473 | addPending(pendingPair, onUnmount);
|
474 | }
|
475 | delete atomState.m;
|
476 | for (var _iterator7 = _createForOfIteratorHelperLoose(atomState.d.keys()), _step7; !(_step7 = _iterator7()).done;) {
|
477 | var a = _step7.value;
|
478 | unmountAtom(pendingPair, a);
|
479 | }
|
480 | var pendingPromise = getPendingContinuablePromise(atomState);
|
481 | if (pendingPromise) {
|
482 | pendingPromise[CONTINUE_PROMISE](undefined, function () {});
|
483 | }
|
484 | }
|
485 | };
|
486 | var subscribeAtom = function subscribeAtom(atom, listener) {
|
487 | var pendingPair = createPendingPair();
|
488 | var mounted = mountAtom(pendingPair, atom);
|
489 | flushPending(pendingPair);
|
490 | var listeners = mounted.l;
|
491 | listeners.add(listener);
|
492 | return function () {
|
493 | listeners.delete(listener);
|
494 | var pendingPair = createPendingPair();
|
495 | unmountAtom(pendingPair, atom);
|
496 | flushPending(pendingPair);
|
497 | };
|
498 | };
|
499 | {
|
500 | var store = {
|
501 | get: readAtom,
|
502 | set: writeAtom,
|
503 | sub: subscribeAtom,
|
504 | dev4_get_internal_weak_map: function dev4_get_internal_weak_map() {
|
505 | return atomStateMap;
|
506 | },
|
507 | dev4_override_method: function dev4_override_method(key, fn) {
|
508 | store[key] = fn;
|
509 | }
|
510 | };
|
511 | return store;
|
512 | }
|
513 | };
|
514 | var defaultStore;
|
515 | var getDefaultStore = function getDefaultStore() {
|
516 | if (!defaultStore) {
|
517 | defaultStore = createStore();
|
518 | {
|
519 | var _ref2;
|
520 | (_ref2 = globalThis).__JOTAI_DEFAULT_STORE__ || (_ref2.__JOTAI_DEFAULT_STORE__ = defaultStore);
|
521 | if (globalThis.__JOTAI_DEFAULT_STORE__ !== defaultStore) {
|
522 | console.warn('Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044');
|
523 | }
|
524 | }
|
525 | }
|
526 | return defaultStore;
|
527 | };
|
528 |
|
529 | exports.atom = atom;
|
530 | exports.createStore = createStore;
|
531 | exports.getDefaultStore = getDefaultStore;
|
532 |
|
533 | }));
|