UNPKG

22.4 kBJavaScriptView Raw
1System.register([], (function (exports) {
2 'use strict';
3 return {
4 execute: (function () {
5
6 exports("atom", atom);
7
8 let keyCount = 0;
9 function atom(read, write) {
10 const key = `atom${++keyCount}`;
11 const config = {
12 toString: () => key
13 };
14 if (typeof read === "function") {
15 config.read = read;
16 } else {
17 config.init = read;
18 config.read = defaultRead;
19 config.write = defaultWrite;
20 }
21 if (write) {
22 config.write = write;
23 }
24 return config;
25 }
26 function defaultRead(get) {
27 return get(this);
28 }
29 function defaultWrite(get, set, arg) {
30 return set(
31 this,
32 typeof arg === "function" ? arg(get(this)) : arg
33 );
34 }
35
36 const isSelfAtom = (atom, a) => atom.unstable_is ? atom.unstable_is(a) : a === atom;
37 const hasInitialValue = (atom) => "init" in atom;
38 const isActuallyWritableAtom = (atom) => !!atom.write;
39 const cancelPromiseMap = /* @__PURE__ */ new WeakMap();
40 const registerCancelPromise = (promise, cancel) => {
41 cancelPromiseMap.set(promise, cancel);
42 promise.catch(() => {
43 }).finally(() => cancelPromiseMap.delete(promise));
44 };
45 const cancelPromise = (promise, next) => {
46 const cancel = cancelPromiseMap.get(promise);
47 if (cancel) {
48 cancelPromiseMap.delete(promise);
49 cancel(next);
50 }
51 };
52 const resolvePromise = (promise, value) => {
53 promise.status = "fulfilled";
54 promise.value = value;
55 };
56 const rejectPromise = (promise, e) => {
57 promise.status = "rejected";
58 promise.reason = e;
59 };
60 const isPromiseLike = (x) => typeof (x == null ? void 0 : x.then) === "function";
61 const isEqualAtomValue = (a, b) => !!a && "v" in a && "v" in b && Object.is(a.v, b.v);
62 const isEqualAtomError = (a, b) => !!a && "e" in a && "e" in b && Object.is(a.e, b.e);
63 const hasPromiseAtomValue = (a) => !!a && "v" in a && a.v instanceof Promise;
64 const isEqualPromiseAtomValue = (a, b) => "v" in a && "v" in b && a.v.orig && a.v.orig === b.v.orig;
65 const returnAtomValue = (atomState) => {
66 if ("e" in atomState) {
67 throw atomState.e;
68 }
69 return atomState.v;
70 };
71 const createStore$1 = () => {
72 const atomStateMap = /* @__PURE__ */ new WeakMap();
73 const mountedMap = /* @__PURE__ */ new WeakMap();
74 const pendingStack = [];
75 const pendingMap = /* @__PURE__ */ new WeakMap();
76 let devListenersRev2;
77 let mountedAtoms;
78 {
79 devListenersRev2 = /* @__PURE__ */ new Set();
80 mountedAtoms = /* @__PURE__ */ new Set();
81 }
82 const getAtomState = (atom) => atomStateMap.get(atom);
83 const addPendingDependent = (atom, atomState) => {
84 atomState.d.forEach((_, a) => {
85 var _a;
86 if (!pendingMap.has(a)) {
87 const aState = getAtomState(a);
88 (_a = pendingStack[pendingStack.length - 1]) == null ? void 0 : _a.add(a);
89 pendingMap.set(a, [aState, /* @__PURE__ */ new Set()]);
90 if (aState) {
91 addPendingDependent(a, aState);
92 }
93 }
94 pendingMap.get(a)[1].add(atom);
95 });
96 };
97 const setAtomState = (atom, atomState) => {
98 var _a;
99 {
100 Object.freeze(atomState);
101 }
102 const prevAtomState = getAtomState(atom);
103 atomStateMap.set(atom, atomState);
104 if (!pendingMap.has(atom)) {
105 (_a = pendingStack[pendingStack.length - 1]) == null ? void 0 : _a.add(atom);
106 pendingMap.set(atom, [prevAtomState, /* @__PURE__ */ new Set()]);
107 addPendingDependent(atom, atomState);
108 }
109 if (hasPromiseAtomValue(prevAtomState)) {
110 const next = "v" in atomState ? atomState.v instanceof Promise ? atomState.v : Promise.resolve(atomState.v) : Promise.reject(atomState.e);
111 if (prevAtomState.v !== next) {
112 cancelPromise(prevAtomState.v, next);
113 }
114 }
115 };
116 const updateDependencies = (atom, nextAtomState, nextDependencies, keepPreviousDependencies) => {
117 const dependencies = new Map(
118 keepPreviousDependencies ? nextAtomState.d : null
119 );
120 let changed = false;
121 nextDependencies.forEach((aState, a) => {
122 if (!aState && isSelfAtom(atom, a)) {
123 aState = nextAtomState;
124 }
125 if (aState) {
126 dependencies.set(a, aState);
127 if (nextAtomState.d.get(a) !== aState) {
128 changed = true;
129 }
130 } else {
131 console.warn("[Bug] atom state not found");
132 }
133 });
134 if (changed || nextAtomState.d.size !== dependencies.size) {
135 nextAtomState.d = dependencies;
136 }
137 };
138 const setAtomValue = (atom, value, nextDependencies, keepPreviousDependencies) => {
139 const prevAtomState = getAtomState(atom);
140 const nextAtomState = {
141 d: (prevAtomState == null ? void 0 : prevAtomState.d) || /* @__PURE__ */ new Map(),
142 v: value
143 };
144 if (nextDependencies) {
145 updateDependencies(
146 atom,
147 nextAtomState,
148 nextDependencies,
149 keepPreviousDependencies
150 );
151 }
152 if (isEqualAtomValue(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
153 return prevAtomState;
154 }
155 if (hasPromiseAtomValue(prevAtomState) && hasPromiseAtomValue(nextAtomState) && isEqualPromiseAtomValue(prevAtomState, nextAtomState)) {
156 if (prevAtomState.d === nextAtomState.d) {
157 return prevAtomState;
158 } else {
159 nextAtomState.v = prevAtomState.v;
160 }
161 }
162 setAtomState(atom, nextAtomState);
163 return nextAtomState;
164 };
165 const setAtomValueOrPromise = (atom, valueOrPromise, nextDependencies, abortPromise) => {
166 if (isPromiseLike(valueOrPromise)) {
167 let continuePromise;
168 const updatePromiseDependencies = () => {
169 const prevAtomState = getAtomState(atom);
170 if (!hasPromiseAtomValue(prevAtomState) || prevAtomState.v !== promise) {
171 return;
172 }
173 const nextAtomState = setAtomValue(
174 atom,
175 promise,
176 nextDependencies
177 );
178 if (mountedMap.has(atom) && prevAtomState.d !== nextAtomState.d) {
179 mountDependencies(atom, nextAtomState, prevAtomState.d);
180 }
181 };
182 const promise = new Promise((resolve, reject) => {
183 let settled = false;
184 valueOrPromise.then(
185 (v) => {
186 if (!settled) {
187 settled = true;
188 resolvePromise(promise, v);
189 resolve(v);
190 updatePromiseDependencies();
191 }
192 },
193 (e) => {
194 if (!settled) {
195 settled = true;
196 rejectPromise(promise, e);
197 reject(e);
198 updatePromiseDependencies();
199 }
200 }
201 );
202 continuePromise = (next) => {
203 if (!settled) {
204 settled = true;
205 next.then(
206 (v) => resolvePromise(promise, v),
207 (e) => rejectPromise(promise, e)
208 );
209 resolve(next);
210 }
211 };
212 });
213 promise.orig = valueOrPromise;
214 promise.status = "pending";
215 registerCancelPromise(promise, (next) => {
216 if (next) {
217 continuePromise(next);
218 }
219 abortPromise == null ? void 0 : abortPromise();
220 });
221 return setAtomValue(atom, promise, nextDependencies, true);
222 }
223 return setAtomValue(atom, valueOrPromise, nextDependencies);
224 };
225 const setAtomError = (atom, error, nextDependencies) => {
226 const prevAtomState = getAtomState(atom);
227 const nextAtomState = {
228 d: (prevAtomState == null ? void 0 : prevAtomState.d) || /* @__PURE__ */ new Map(),
229 e: error
230 };
231 if (nextDependencies) {
232 updateDependencies(atom, nextAtomState, nextDependencies);
233 }
234 if (isEqualAtomError(prevAtomState, nextAtomState) && prevAtomState.d === nextAtomState.d) {
235 return prevAtomState;
236 }
237 setAtomState(atom, nextAtomState);
238 return nextAtomState;
239 };
240 const readAtomState = (atom, force) => {
241 const atomState = getAtomState(atom);
242 if (!force && atomState) {
243 if (mountedMap.has(atom)) {
244 return atomState;
245 }
246 if (Array.from(atomState.d).every(([a, s]) => {
247 if (a === atom) {
248 return true;
249 }
250 const aState = readAtomState(a);
251 return aState === s || isEqualAtomValue(aState, s);
252 })) {
253 return atomState;
254 }
255 }
256 const nextDependencies = /* @__PURE__ */ new Map();
257 let isSync = true;
258 const getter = (a) => {
259 if (isSelfAtom(atom, a)) {
260 const aState2 = getAtomState(a);
261 if (aState2) {
262 nextDependencies.set(a, aState2);
263 return returnAtomValue(aState2);
264 }
265 if (hasInitialValue(a)) {
266 nextDependencies.set(a, void 0);
267 return a.init;
268 }
269 throw new Error("no atom init");
270 }
271 const aState = readAtomState(a);
272 nextDependencies.set(a, aState);
273 return returnAtomValue(aState);
274 };
275 let controller;
276 let setSelf;
277 const options = {
278 get signal() {
279 if (!controller) {
280 controller = new AbortController();
281 }
282 return controller.signal;
283 },
284 get setSelf() {
285 if (!isActuallyWritableAtom(atom)) {
286 console.warn("setSelf function cannot be used with read-only atom");
287 }
288 if (!setSelf && isActuallyWritableAtom(atom)) {
289 setSelf = (...args) => {
290 if (isSync) {
291 console.warn("setSelf function cannot be called in sync");
292 }
293 if (!isSync) {
294 return writeAtom(atom, ...args);
295 }
296 };
297 }
298 return setSelf;
299 }
300 };
301 try {
302 const valueOrPromise = atom.read(getter, options);
303 return setAtomValueOrPromise(
304 atom,
305 valueOrPromise,
306 nextDependencies,
307 () => controller == null ? void 0 : controller.abort()
308 );
309 } catch (error) {
310 return setAtomError(atom, error, nextDependencies);
311 } finally {
312 isSync = false;
313 }
314 };
315 const readAtom = (atom) => returnAtomValue(readAtomState(atom));
316 const recomputeDependents = (atom) => {
317 const getDependents = (a) => {
318 var _a, _b;
319 const dependents = new Set((_a = mountedMap.get(a)) == null ? void 0 : _a.t);
320 (_b = pendingMap.get(a)) == null ? void 0 : _b[1].forEach((dependent) => {
321 dependents.add(dependent);
322 });
323 return dependents;
324 };
325 const topsortedAtoms = new Array();
326 const markedAtoms = /* @__PURE__ */ new Set();
327 const visit = (n) => {
328 if (markedAtoms.has(n)) {
329 return;
330 }
331 markedAtoms.add(n);
332 for (const m of getDependents(n)) {
333 if (n !== m) {
334 visit(m);
335 }
336 }
337 topsortedAtoms.push(n);
338 };
339 visit(atom);
340 const changedAtoms = /* @__PURE__ */ new Set([atom]);
341 for (let i = topsortedAtoms.length - 1; i >= 0; --i) {
342 const a = topsortedAtoms[i];
343 const prevAtomState = getAtomState(a);
344 if (!prevAtomState) {
345 continue;
346 }
347 let hasChangedDeps = false;
348 for (const dep of prevAtomState.d.keys()) {
349 if (dep !== a && changedAtoms.has(dep)) {
350 hasChangedDeps = true;
351 break;
352 }
353 }
354 if (hasChangedDeps) {
355 const nextAtomState = readAtomState(a, true);
356 if (!isEqualAtomValue(prevAtomState, nextAtomState)) {
357 changedAtoms.add(a);
358 }
359 }
360 }
361 };
362 const writeAtomState = (atom, ...args) => {
363 const getter = (a) => returnAtomValue(readAtomState(a));
364 const setter = (a, ...args2) => {
365 const isSync = pendingStack.length > 0;
366 if (!isSync) {
367 pendingStack.push(/* @__PURE__ */ new Set([a]));
368 }
369 let r;
370 if (isSelfAtom(atom, a)) {
371 if (!hasInitialValue(a)) {
372 throw new Error("atom not writable");
373 }
374 const prevAtomState = getAtomState(a);
375 const nextAtomState = setAtomValueOrPromise(a, args2[0]);
376 if (!isEqualAtomValue(prevAtomState, nextAtomState)) {
377 recomputeDependents(a);
378 }
379 } else {
380 r = writeAtomState(a, ...args2);
381 }
382 if (!isSync) {
383 const flushed = flushPending(pendingStack.pop());
384 {
385 devListenersRev2.forEach(
386 (l) => l({ type: "async-write", flushed })
387 );
388 }
389 }
390 return r;
391 };
392 const result = atom.write(getter, setter, ...args);
393 return result;
394 };
395 const writeAtom = (atom, ...args) => {
396 pendingStack.push(/* @__PURE__ */ new Set([atom]));
397 const result = writeAtomState(atom, ...args);
398 const flushed = flushPending(pendingStack.pop());
399 {
400 devListenersRev2.forEach((l) => l({ type: "write", flushed }));
401 }
402 return result;
403 };
404 const mountAtom = (atom, initialDependent, onMountQueue) => {
405 var _a;
406 const existingMount = mountedMap.get(atom);
407 if (existingMount) {
408 if (initialDependent) {
409 existingMount.t.add(initialDependent);
410 }
411 return existingMount;
412 }
413 const queue = onMountQueue || [];
414 (_a = getAtomState(atom)) == null ? void 0 : _a.d.forEach((_, a) => {
415 if (a !== atom) {
416 mountAtom(a, atom, queue);
417 }
418 });
419 readAtomState(atom);
420 const mounted = {
421 t: new Set(initialDependent && [initialDependent]),
422 l: /* @__PURE__ */ new Set()
423 };
424 mountedMap.set(atom, mounted);
425 {
426 mountedAtoms.add(atom);
427 }
428 if (isActuallyWritableAtom(atom) && atom.onMount) {
429 const { onMount } = atom;
430 queue.push(() => {
431 const onUnmount = onMount((...args) => writeAtom(atom, ...args));
432 if (onUnmount) {
433 mounted.u = onUnmount;
434 }
435 });
436 }
437 if (!onMountQueue) {
438 queue.forEach((f) => f());
439 }
440 return mounted;
441 };
442 const canUnmountAtom = (atom, mounted) => !mounted.l.size && (!mounted.t.size || mounted.t.size === 1 && mounted.t.has(atom));
443 const tryUnmountAtom = (atom, mounted) => {
444 if (!canUnmountAtom(atom, mounted)) {
445 return;
446 }
447 const onUnmount = mounted.u;
448 if (onUnmount) {
449 onUnmount();
450 }
451 mountedMap.delete(atom);
452 {
453 mountedAtoms.delete(atom);
454 }
455 const atomState = getAtomState(atom);
456 if (atomState) {
457 if (hasPromiseAtomValue(atomState)) {
458 cancelPromise(atomState.v);
459 }
460 atomState.d.forEach((_, a) => {
461 if (a !== atom) {
462 const mountedDep = mountedMap.get(a);
463 if (mountedDep) {
464 mountedDep.t.delete(atom);
465 tryUnmountAtom(a, mountedDep);
466 }
467 }
468 });
469 } else {
470 console.warn("[Bug] could not find atom state to unmount", atom);
471 }
472 };
473 const mountDependencies = (atom, atomState, prevDependencies) => {
474 const depSet = new Set(atomState.d.keys());
475 const maybeUnmountAtomSet = /* @__PURE__ */ new Set();
476 prevDependencies == null ? void 0 : prevDependencies.forEach((_, a) => {
477 if (depSet.has(a)) {
478 depSet.delete(a);
479 return;
480 }
481 maybeUnmountAtomSet.add(a);
482 const mounted = mountedMap.get(a);
483 if (mounted) {
484 mounted.t.delete(atom);
485 }
486 });
487 depSet.forEach((a) => {
488 mountAtom(a, atom);
489 });
490 maybeUnmountAtomSet.forEach((a) => {
491 const mounted = mountedMap.get(a);
492 if (mounted) {
493 tryUnmountAtom(a, mounted);
494 }
495 });
496 };
497 const flushPending = (pendingAtoms) => {
498 let flushed;
499 {
500 flushed = /* @__PURE__ */ new Set();
501 }
502 const pending = [];
503 const collectPending = (pendingAtom) => {
504 var _a;
505 if (!pendingMap.has(pendingAtom)) {
506 return;
507 }
508 const [prevAtomState, dependents] = pendingMap.get(pendingAtom);
509 pendingMap.delete(pendingAtom);
510 pending.push([pendingAtom, prevAtomState]);
511 dependents.forEach(collectPending);
512 (_a = getAtomState(pendingAtom)) == null ? void 0 : _a.d.forEach((_, a) => collectPending(a));
513 };
514 pendingAtoms.forEach(collectPending);
515 pending.forEach(([atom, prevAtomState]) => {
516 const atomState = getAtomState(atom);
517 if (!atomState) {
518 {
519 console.warn("[Bug] no atom state to flush");
520 }
521 return;
522 }
523 if (atomState !== prevAtomState) {
524 const mounted = mountedMap.get(atom);
525 if (mounted && atomState.d !== (prevAtomState == null ? void 0 : prevAtomState.d)) {
526 mountDependencies(atom, atomState, prevAtomState == null ? void 0 : prevAtomState.d);
527 }
528 if (mounted && !// TODO This seems pretty hacky. Hope to fix it.
529 // Maybe we could `mountDependencies` in `setAtomState`?
530 (!hasPromiseAtomValue(prevAtomState) && (isEqualAtomValue(prevAtomState, atomState) || isEqualAtomError(prevAtomState, atomState)))) {
531 mounted.l.forEach((listener) => listener());
532 {
533 flushed.add(atom);
534 }
535 }
536 }
537 });
538 {
539 return flushed;
540 }
541 };
542 const subscribeAtom = (atom, listener) => {
543 const mounted = mountAtom(atom);
544 const flushed = flushPending([atom]);
545 const listeners = mounted.l;
546 listeners.add(listener);
547 {
548 devListenersRev2.forEach(
549 (l) => l({ type: "sub", flushed })
550 );
551 }
552 return () => {
553 listeners.delete(listener);
554 tryUnmountAtom(atom, mounted);
555 {
556 devListenersRev2.forEach((l) => l({ type: "unsub" }));
557 }
558 };
559 };
560 {
561 return {
562 get: readAtom,
563 set: writeAtom,
564 sub: subscribeAtom,
565 // store dev methods (these are tentative and subject to change without notice)
566 dev_subscribe_store: (l) => {
567 devListenersRev2.add(l);
568 return () => {
569 devListenersRev2.delete(l);
570 };
571 },
572 dev_get_mounted_atoms: () => mountedAtoms.values(),
573 dev_get_atom_state: (a) => atomStateMap.get(a),
574 dev_get_mounted: (a) => mountedMap.get(a),
575 dev_restore_atoms: (values) => {
576 pendingStack.push(/* @__PURE__ */ new Set());
577 for (const [atom, valueOrPromise] of values) {
578 if (hasInitialValue(atom)) {
579 setAtomValueOrPromise(atom, valueOrPromise);
580 recomputeDependents(atom);
581 }
582 }
583 const flushed = flushPending(pendingStack.pop());
584 devListenersRev2.forEach(
585 (l) => l({ type: "restore", flushed })
586 );
587 }
588 };
589 }
590 };
591 let defaultStore;
592 const getDefaultStore$1 = () => {
593 if (!defaultStore) {
594 defaultStore = createStore$1();
595 {
596 globalThis.__JOTAI_DEFAULT_STORE__ || (globalThis.__JOTAI_DEFAULT_STORE__ = defaultStore);
597 if (globalThis.__JOTAI_DEFAULT_STORE__ !== defaultStore) {
598 console.warn(
599 "Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044"
600 );
601 }
602 }
603 }
604 return defaultStore;
605 };
606
607 const createStore = exports("createStore", createStore$1);
608 const getDefaultStore = exports("getDefaultStore", getDefaultStore$1);
609
610 })
611 };
612}));