UNPKG

15.9 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 createPendingPair = () => [/* @__PURE__ */ new Set(), /* @__PURE__ */ new Set()];
40 const addPending = (pendingPair, pending) => {
41 (pendingPair[0] || pendingPair[1]).add(pending);
42 };
43 const flushPending = (pendingPair, isAsync) => {
44 let pendingSet;
45 if (isAsync) {
46 if (pendingPair[0]) {
47 return;
48 }
49 pendingSet = pendingPair[1];
50 } else {
51 if (!pendingPair[0]) {
52 throw new Error("[Bug] cannot sync flush twice");
53 }
54 pendingSet = pendingPair[0];
55 }
56 const flushed = /* @__PURE__ */ new Set();
57 while (pendingSet.size) {
58 const copy = new Set(pendingSet);
59 pendingSet.clear();
60 copy.forEach((pending) => {
61 if (typeof pending === "function") {
62 pending();
63 } else {
64 const [atom, atomState] = pending;
65 if (!flushed.has(atom) && atomState.m) {
66 atomState.m.l.forEach((listener) => listener());
67 flushed.add(atom);
68 }
69 }
70 });
71 }
72 pendingPair[0] = void 0;
73 return flushed;
74 };
75 const CONTINUE_PROMISE = Symbol(
76 "CONTINUE_PROMISE"
77 );
78 const PENDING = "pending";
79 const FULFILLED = "fulfilled";
80 const REJECTED = "rejected";
81 const isContinuablePromise = (promise) => typeof promise === "object" && promise !== null && CONTINUE_PROMISE in promise;
82 const continuablePromiseMap = /* @__PURE__ */ new WeakMap();
83 const createContinuablePromise = (promise, abort, complete) => {
84 if (!continuablePromiseMap.has(promise)) {
85 let continuePromise;
86 const p = new Promise((resolve, reject) => {
87 let curr = promise;
88 const onFullfilled = (me) => (v) => {
89 if (curr === me) {
90 p.status = FULFILLED;
91 p.value = v;
92 resolve(v);
93 complete();
94 }
95 };
96 const onRejected = (me) => (e) => {
97 if (curr === me) {
98 p.status = REJECTED;
99 p.reason = e;
100 reject(e);
101 complete();
102 }
103 };
104 promise.then(onFullfilled(promise), onRejected(promise));
105 continuePromise = (nextPromise, nextAbort) => {
106 if (nextPromise) {
107 continuablePromiseMap.set(nextPromise, p);
108 curr = nextPromise;
109 nextPromise.then(onFullfilled(nextPromise), onRejected(nextPromise));
110 }
111 abort();
112 abort = nextAbort;
113 };
114 });
115 p.status = PENDING;
116 p[CONTINUE_PROMISE] = continuePromise;
117 continuablePromiseMap.set(promise, p);
118 }
119 return continuablePromiseMap.get(promise);
120 };
121 const isPromiseLike = (x) => typeof (x == null ? void 0 : x.then) === "function";
122 const getPendingContinuablePromise = (atomState) => {
123 var _a;
124 const value = (_a = atomState.s) == null ? void 0 : _a.v;
125 if (isContinuablePromise(value) && value.status === PENDING) {
126 return value;
127 }
128 return null;
129 };
130 const returnAtomValue = (atomState) => {
131 if ("e" in atomState.s) {
132 throw atomState.s.e;
133 }
134 return atomState.s.v;
135 };
136 const setAtomStateValueOrPromise = (atomState, valueOrPromise, abortPromise = () => {
137 }, completePromise = () => {
138 }) => {
139 const pendingPromise = getPendingContinuablePromise(atomState);
140 if (isPromiseLike(valueOrPromise)) {
141 if (pendingPromise) {
142 if (pendingPromise !== valueOrPromise) {
143 pendingPromise[CONTINUE_PROMISE](valueOrPromise, abortPromise);
144 }
145 } else {
146 const continuablePromise = createContinuablePromise(
147 valueOrPromise,
148 abortPromise,
149 completePromise
150 );
151 atomState.s = { v: continuablePromise };
152 }
153 } else {
154 if (pendingPromise) {
155 pendingPromise[CONTINUE_PROMISE](
156 Promise.resolve(valueOrPromise),
157 abortPromise
158 );
159 }
160 atomState.s = { v: valueOrPromise };
161 }
162 };
163 const createStore = exports("createStore", () => {
164 const atomStateMap = /* @__PURE__ */ new WeakMap();
165 const getAtomState = (atom) => {
166 let atomState = atomStateMap.get(atom);
167 if (!atomState) {
168 atomState = { d: /* @__PURE__ */ new Map(), t: /* @__PURE__ */ new Set() };
169 atomStateMap.set(atom, atomState);
170 }
171 return atomState;
172 };
173 const clearDependencies = (atom) => {
174 const atomState = getAtomState(atom);
175 for (const a of atomState.d.keys()) {
176 getAtomState(a).t.delete(atom);
177 }
178 atomState.d.clear();
179 };
180 const addDependency = (atom, a, aState, isSync) => {
181 if (a === atom) {
182 throw new Error("[Bug] atom cannot depend on itself");
183 }
184 const atomState = getAtomState(atom);
185 atomState.d.set(a, aState.s);
186 aState.t.add(atom);
187 if (!isSync && atomState.m) {
188 const pendingPair = createPendingPair();
189 mountDependencies(pendingPair, atomState);
190 flushPending(pendingPair);
191 }
192 };
193 const readAtomState = (atom, force) => {
194 const atomState = getAtomState(atom);
195 if (!force && "s" in atomState) {
196 if (atomState.m) {
197 return atomState;
198 }
199 if (Array.from(atomState.d).every(([a, s]) => {
200 const aState = readAtomState(a);
201 return "v" in s && "v" in aState.s && Object.is(s.v, aState.s.v);
202 })) {
203 return atomState;
204 }
205 }
206 clearDependencies(atom);
207 let isSync = true;
208 const getter = (a) => {
209 if (isSelfAtom(atom, a)) {
210 const aState2 = getAtomState(a);
211 if (!aState2.s) {
212 if (hasInitialValue(a)) {
213 setAtomStateValueOrPromise(aState2, a.init);
214 } else {
215 throw new Error("no atom init");
216 }
217 }
218 return returnAtomValue(aState2);
219 }
220 const aState = readAtomState(a);
221 addDependency(atom, a, aState, isSync);
222 return returnAtomValue(aState);
223 };
224 let controller;
225 let setSelf;
226 const options = {
227 get signal() {
228 if (!controller) {
229 controller = new AbortController();
230 }
231 return controller.signal;
232 },
233 get setSelf() {
234 if (!isActuallyWritableAtom(atom)) {
235 console.warn("setSelf function cannot be used with read-only atom");
236 }
237 if (!setSelf && isActuallyWritableAtom(atom)) {
238 setSelf = (...args) => {
239 if (isSync) {
240 console.warn("setSelf function cannot be called in sync");
241 }
242 if (!isSync) {
243 return writeAtom(atom, ...args);
244 }
245 };
246 }
247 return setSelf;
248 }
249 };
250 try {
251 const valueOrPromise = atom.read(getter, options);
252 setAtomStateValueOrPromise(
253 atomState,
254 valueOrPromise,
255 () => controller == null ? void 0 : controller.abort(),
256 () => {
257 if (atomState.m) {
258 const pendingPair = createPendingPair();
259 mountDependencies(pendingPair, atomState);
260 flushPending(pendingPair);
261 }
262 }
263 );
264 return atomState;
265 } catch (error) {
266 atomState.s = { e: error };
267 return atomState;
268 } finally {
269 isSync = false;
270 }
271 };
272 const readAtom = (atom) => returnAtomValue(readAtomState(atom));
273 const recomputeDependents = (pendingPair, atom) => {
274 const topsortedAtoms = [];
275 const markedAtoms = /* @__PURE__ */ new Set();
276 const visit = (n) => {
277 if (markedAtoms.has(n)) {
278 return;
279 }
280 markedAtoms.add(n);
281 for (const m of getAtomState(n).t) {
282 if (n !== m) {
283 visit(m);
284 }
285 }
286 topsortedAtoms.push(n);
287 };
288 visit(atom);
289 const changedAtoms = /* @__PURE__ */ new Set([atom]);
290 for (let i = topsortedAtoms.length - 1; i >= 0; --i) {
291 const a = topsortedAtoms[i];
292 const aState = getAtomState(a);
293 const prev = aState.s;
294 let hasChangedDeps = false;
295 for (const dep of aState.d.keys()) {
296 if (dep !== a && changedAtoms.has(dep)) {
297 hasChangedDeps = true;
298 break;
299 }
300 }
301 if (hasChangedDeps) {
302 if (aState.m || getPendingContinuablePromise(aState)) {
303 readAtomState(a, true);
304 mountDependencies(pendingPair, aState);
305 if (!prev || !("v" in prev) || !("v" in aState.s) || !Object.is(prev.v, aState.s.v)) {
306 addPending(pendingPair, [a, aState]);
307 changedAtoms.add(a);
308 }
309 }
310 }
311 }
312 };
313 const writeAtomState = (pendingPair, atom, ...args) => {
314 const getter = (a) => returnAtomValue(readAtomState(a));
315 const setter = (a, ...args2) => {
316 let r;
317 if (isSelfAtom(atom, a)) {
318 if (!hasInitialValue(a)) {
319 throw new Error("atom not writable");
320 }
321 const aState = getAtomState(a);
322 const prev = aState.s;
323 const v = args2[0];
324 setAtomStateValueOrPromise(aState, v);
325 mountDependencies(pendingPair, aState);
326 const curr = aState.s;
327 if (!prev || !("v" in prev) || !("v" in curr) || !Object.is(prev.v, curr.v)) {
328 addPending(pendingPair, [a, aState]);
329 recomputeDependents(pendingPair, a);
330 }
331 } else {
332 r = writeAtomState(pendingPair, a, ...args2);
333 }
334 flushPending(pendingPair, true);
335 return r;
336 };
337 const result = atom.write(getter, setter, ...args);
338 return result;
339 };
340 const writeAtom = (atom, ...args) => {
341 const pendingPair = createPendingPair();
342 const result = writeAtomState(pendingPair, atom, ...args);
343 flushPending(pendingPair);
344 return result;
345 };
346 const mountDependencies = (pendingPair, atomState) => {
347 if (atomState.m && !getPendingContinuablePromise(atomState)) {
348 for (const a of atomState.d.keys()) {
349 if (!atomState.m.d.has(a)) {
350 mountAtom(pendingPair, a);
351 atomState.m.d.add(a);
352 }
353 }
354 for (const a of atomState.m.d || []) {
355 if (!atomState.d.has(a)) {
356 unmountAtom(pendingPair, a);
357 atomState.m.d.delete(a);
358 }
359 }
360 }
361 };
362 const mountAtom = (pendingPair, atom) => {
363 const atomState = getAtomState(atom);
364 if (!atomState.m) {
365 readAtomState(atom);
366 for (const a of atomState.d.keys()) {
367 mountAtom(pendingPair, a);
368 }
369 atomState.m = { l: /* @__PURE__ */ new Set(), d: new Set(atomState.d.keys()) };
370 if (isActuallyWritableAtom(atom) && atom.onMount) {
371 const mounted = atomState.m;
372 const { onMount } = atom;
373 addPending(pendingPair, () => {
374 const onUnmount = onMount(
375 (...args) => writeAtomState(pendingPair, atom, ...args)
376 );
377 if (onUnmount) {
378 mounted.u = onUnmount;
379 }
380 });
381 }
382 }
383 return atomState.m;
384 };
385 const unmountAtom = (pendingPair, atom) => {
386 const atomState = getAtomState(atom);
387 if (atomState.m && !atomState.m.l.size && !Array.from(atomState.t).some((a) => getAtomState(a).m)) {
388 const onUnmount = atomState.m.u;
389 if (onUnmount) {
390 addPending(pendingPair, onUnmount);
391 }
392 delete atomState.m;
393 for (const a of atomState.d.keys()) {
394 unmountAtom(pendingPair, a);
395 }
396 const pendingPromise = getPendingContinuablePromise(atomState);
397 if (pendingPromise) {
398 pendingPromise[CONTINUE_PROMISE](void 0, () => {
399 });
400 }
401 }
402 };
403 const subscribeAtom = (atom, listener) => {
404 const pendingPair = createPendingPair();
405 const mounted = mountAtom(pendingPair, atom);
406 flushPending(pendingPair);
407 const listeners = mounted.l;
408 listeners.add(listener);
409 return () => {
410 listeners.delete(listener);
411 const pendingPair2 = createPendingPair();
412 unmountAtom(pendingPair2, atom);
413 flushPending(pendingPair2);
414 };
415 };
416 {
417 const store = {
418 get: readAtom,
419 set: writeAtom,
420 sub: subscribeAtom,
421 // store dev methods (these are tentative and subject to change without notice)
422 dev4_get_internal_weak_map: () => atomStateMap,
423 dev4_override_method: (key, fn) => {
424 store[key] = fn;
425 }
426 };
427 return store;
428 }
429 });
430 let defaultStore;
431 const getDefaultStore = exports("getDefaultStore", () => {
432 if (!defaultStore) {
433 defaultStore = createStore();
434 {
435 globalThis.__JOTAI_DEFAULT_STORE__ || (globalThis.__JOTAI_DEFAULT_STORE__ = defaultStore);
436 if (globalThis.__JOTAI_DEFAULT_STORE__ !== defaultStore) {
437 console.warn(
438 "Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044"
439 );
440 }
441 }
442 }
443 return defaultStore;
444 });
445
446 })
447 };
448}));