612 lines
21 KiB
JavaScript
612 lines
21 KiB
JavaScript
System.register([], (function (exports) {
|
|
'use strict';
|
|
return {
|
|
execute: (function () {
|
|
|
|
exports("atom", atom);
|
|
|
|
let keyCount = 0;
|
|
function atom(read, write) {
|
|
const key = `atom${++keyCount}`;
|
|
const config = {
|
|
toString() {
|
|
return this.debugLabel ? key + ":" + this.debugLabel : key;
|
|
}
|
|
};
|
|
if (typeof read === "function") {
|
|
config.read = read;
|
|
} else {
|
|
config.init = read;
|
|
config.read = defaultRead;
|
|
config.write = defaultWrite;
|
|
}
|
|
if (write) {
|
|
config.write = write;
|
|
}
|
|
return config;
|
|
}
|
|
function defaultRead(get) {
|
|
return get(this);
|
|
}
|
|
function defaultWrite(get, set, arg) {
|
|
return set(
|
|
this,
|
|
typeof arg === "function" ? arg(get(this)) : arg
|
|
);
|
|
}
|
|
|
|
const isSelfAtom = (atom, a) => atom.unstable_is ? atom.unstable_is(a) : a === atom;
|
|
const hasInitialValue = (atom) => "init" in atom;
|
|
const isActuallyWritableAtom = (atom) => !!atom.write;
|
|
const cancelablePromiseMap = /* @__PURE__ */ new WeakMap();
|
|
const isPendingPromise = (value) => {
|
|
var _a;
|
|
return isPromiseLike(value) && !((_a = cancelablePromiseMap.get(value)) == null ? void 0 : _a[1]);
|
|
};
|
|
const cancelPromise = (promise, nextValue) => {
|
|
const promiseState = cancelablePromiseMap.get(promise);
|
|
if (promiseState) {
|
|
promiseState[1] = true;
|
|
promiseState[0].forEach((fn) => fn(nextValue));
|
|
} else {
|
|
throw new Error("[Bug] cancelable promise not found");
|
|
}
|
|
};
|
|
const patchPromiseForCancelability = (promise) => {
|
|
if (cancelablePromiseMap.has(promise)) {
|
|
return;
|
|
}
|
|
const promiseState = [/* @__PURE__ */ new Set(), false];
|
|
cancelablePromiseMap.set(promise, promiseState);
|
|
const settle = () => {
|
|
promiseState[1] = true;
|
|
};
|
|
promise.then(settle, settle);
|
|
promise.onCancel = (fn) => {
|
|
promiseState[0].add(fn);
|
|
};
|
|
};
|
|
const isPromiseLike = (x) => typeof (x == null ? void 0 : x.then) === "function";
|
|
const isAtomStateInitialized = (atomState) => "v" in atomState || "e" in atomState;
|
|
const returnAtomValue = (atomState) => {
|
|
if ("e" in atomState) {
|
|
throw atomState.e;
|
|
}
|
|
if (!("v" in atomState)) {
|
|
throw new Error("[Bug] atom state is not initialized");
|
|
}
|
|
return atomState.v;
|
|
};
|
|
const addPendingPromiseToDependency = (atom, promise, dependencyAtomState) => {
|
|
if (!dependencyAtomState.p.has(atom)) {
|
|
dependencyAtomState.p.add(atom);
|
|
promise.then(
|
|
() => {
|
|
dependencyAtomState.p.delete(atom);
|
|
},
|
|
() => {
|
|
dependencyAtomState.p.delete(atom);
|
|
}
|
|
);
|
|
}
|
|
};
|
|
const addDependency = (batch, atom, atomState, a, aState) => {
|
|
var _a;
|
|
if (a === atom) {
|
|
throw new Error("[Bug] atom cannot depend on itself");
|
|
}
|
|
atomState.d.set(a, aState.n);
|
|
if (isPendingPromise(atomState.v)) {
|
|
addPendingPromiseToDependency(atom, atomState.v, aState);
|
|
}
|
|
(_a = aState.m) == null ? void 0 : _a.t.add(atom);
|
|
if (batch) {
|
|
addBatchAtomDependent(batch, a, atom);
|
|
}
|
|
};
|
|
const createBatch = () => ({
|
|
D: /* @__PURE__ */ new Map(),
|
|
H: /* @__PURE__ */ new Set(),
|
|
M: /* @__PURE__ */ new Set(),
|
|
L: /* @__PURE__ */ new Set()
|
|
});
|
|
const addBatchFunc = (batch, priority, fn) => {
|
|
batch[priority].add(fn);
|
|
};
|
|
const registerBatchAtom = (batch, atom, atomState) => {
|
|
if (!batch.D.has(atom)) {
|
|
batch.D.set(atom, /* @__PURE__ */ new Set());
|
|
addBatchFunc(batch, "M", () => {
|
|
var _a;
|
|
(_a = atomState.m) == null ? void 0 : _a.l.forEach((listener) => addBatchFunc(batch, "M", listener));
|
|
});
|
|
}
|
|
};
|
|
const addBatchAtomDependent = (batch, atom, dependent) => {
|
|
const dependents = batch.D.get(atom);
|
|
if (dependents) {
|
|
dependents.add(dependent);
|
|
}
|
|
};
|
|
const getBatchAtomDependents = (batch, atom) => batch.D.get(atom);
|
|
const flushBatch = (batch) => {
|
|
let error;
|
|
let hasError = false;
|
|
const call = (fn) => {
|
|
try {
|
|
fn();
|
|
} catch (e) {
|
|
if (!hasError) {
|
|
error = e;
|
|
hasError = true;
|
|
}
|
|
}
|
|
};
|
|
while (batch.H.size || batch.M.size || batch.L.size) {
|
|
batch.D.clear();
|
|
batch.H.forEach(call);
|
|
batch.H.clear();
|
|
batch.M.forEach(call);
|
|
batch.M.clear();
|
|
batch.L.forEach(call);
|
|
batch.L.clear();
|
|
}
|
|
if (hasError) {
|
|
throw error;
|
|
}
|
|
};
|
|
const buildStore = (...[getAtomState, atomRead, atomWrite, atomOnMount]) => {
|
|
const setAtomStateValueOrPromise = (atom, atomState, valueOrPromise) => {
|
|
const hasPrevValue = "v" in atomState;
|
|
const prevValue = atomState.v;
|
|
const pendingPromise = isPendingPromise(atomState.v) ? atomState.v : null;
|
|
if (isPromiseLike(valueOrPromise)) {
|
|
patchPromiseForCancelability(valueOrPromise);
|
|
for (const a of atomState.d.keys()) {
|
|
addPendingPromiseToDependency(atom, valueOrPromise, getAtomState(a));
|
|
}
|
|
atomState.v = valueOrPromise;
|
|
} else {
|
|
atomState.v = valueOrPromise;
|
|
}
|
|
delete atomState.e;
|
|
delete atomState.x;
|
|
if (!hasPrevValue || !Object.is(prevValue, atomState.v)) {
|
|
++atomState.n;
|
|
if (pendingPromise) {
|
|
cancelPromise(pendingPromise, valueOrPromise);
|
|
}
|
|
}
|
|
};
|
|
const readAtomState = (batch, atom) => {
|
|
var _a;
|
|
const atomState = getAtomState(atom);
|
|
if (isAtomStateInitialized(atomState)) {
|
|
if (atomState.m && !atomState.x) {
|
|
return atomState;
|
|
}
|
|
if (Array.from(atomState.d).every(
|
|
([a, n]) => (
|
|
// Recursively, read the atom state of the dependency, and
|
|
// check if the atom epoch number is unchanged
|
|
readAtomState(batch, a).n === n
|
|
)
|
|
)) {
|
|
return atomState;
|
|
}
|
|
}
|
|
atomState.d.clear();
|
|
let isSync = true;
|
|
const getter = (a) => {
|
|
if (isSelfAtom(atom, a)) {
|
|
const aState2 = getAtomState(a);
|
|
if (!isAtomStateInitialized(aState2)) {
|
|
if (hasInitialValue(a)) {
|
|
setAtomStateValueOrPromise(a, aState2, a.init);
|
|
} else {
|
|
throw new Error("no atom init");
|
|
}
|
|
}
|
|
return returnAtomValue(aState2);
|
|
}
|
|
const aState = readAtomState(batch, a);
|
|
try {
|
|
return returnAtomValue(aState);
|
|
} finally {
|
|
if (isSync) {
|
|
addDependency(batch, atom, atomState, a, aState);
|
|
} else {
|
|
const batch2 = createBatch();
|
|
addDependency(batch2, atom, atomState, a, aState);
|
|
mountDependencies(batch2, atom, atomState);
|
|
flushBatch(batch2);
|
|
}
|
|
}
|
|
};
|
|
let controller;
|
|
let setSelf;
|
|
const options = {
|
|
get signal() {
|
|
if (!controller) {
|
|
controller = new AbortController();
|
|
}
|
|
return controller.signal;
|
|
},
|
|
get setSelf() {
|
|
if (!isActuallyWritableAtom(atom)) {
|
|
console.warn("setSelf function cannot be used with read-only atom");
|
|
}
|
|
if (!setSelf && isActuallyWritableAtom(atom)) {
|
|
setSelf = (...args) => {
|
|
if (isSync) {
|
|
console.warn("setSelf function cannot be called in sync");
|
|
}
|
|
if (!isSync) {
|
|
return writeAtom(atom, ...args);
|
|
}
|
|
};
|
|
}
|
|
return setSelf;
|
|
}
|
|
};
|
|
try {
|
|
const valueOrPromise = atomRead(atom, getter, options);
|
|
setAtomStateValueOrPromise(atom, atomState, valueOrPromise);
|
|
if (isPromiseLike(valueOrPromise)) {
|
|
(_a = valueOrPromise.onCancel) == null ? void 0 : _a.call(valueOrPromise, () => controller == null ? void 0 : controller.abort());
|
|
const complete = () => {
|
|
if (atomState.m) {
|
|
const batch2 = createBatch();
|
|
mountDependencies(batch2, atom, atomState);
|
|
flushBatch(batch2);
|
|
}
|
|
};
|
|
valueOrPromise.then(complete, complete);
|
|
}
|
|
return atomState;
|
|
} catch (error) {
|
|
delete atomState.v;
|
|
atomState.e = error;
|
|
delete atomState.x;
|
|
++atomState.n;
|
|
return atomState;
|
|
} finally {
|
|
isSync = false;
|
|
}
|
|
};
|
|
const readAtom = (atom) => returnAtomValue(readAtomState(void 0, atom));
|
|
const getMountedOrBatchDependents = (batch, atom, atomState) => {
|
|
var _a, _b;
|
|
const dependents = /* @__PURE__ */ new Map();
|
|
for (const a of ((_a = atomState.m) == null ? void 0 : _a.t) || []) {
|
|
const aState = getAtomState(a);
|
|
if (aState.m) {
|
|
dependents.set(a, aState);
|
|
}
|
|
}
|
|
for (const atomWithPendingPromise of atomState.p) {
|
|
dependents.set(
|
|
atomWithPendingPromise,
|
|
getAtomState(atomWithPendingPromise)
|
|
);
|
|
}
|
|
(_b = getBatchAtomDependents(batch, atom)) == null ? void 0 : _b.forEach((dependent) => {
|
|
dependents.set(dependent, getAtomState(dependent));
|
|
});
|
|
return dependents;
|
|
};
|
|
const recomputeDependents = (batch, atom, atomState) => {
|
|
const topSortedReversed = [];
|
|
const visiting = /* @__PURE__ */ new Set();
|
|
const visited = /* @__PURE__ */ new Set();
|
|
const stack = [[atom, atomState]];
|
|
while (stack.length > 0) {
|
|
const [a, aState] = stack[stack.length - 1];
|
|
if (visited.has(a)) {
|
|
stack.pop();
|
|
continue;
|
|
}
|
|
if (visiting.has(a)) {
|
|
topSortedReversed.push([a, aState, aState.n]);
|
|
visited.add(a);
|
|
aState.x = true;
|
|
stack.pop();
|
|
continue;
|
|
}
|
|
visiting.add(a);
|
|
for (const [d, s] of getMountedOrBatchDependents(batch, a, aState)) {
|
|
if (a !== d && !visiting.has(d)) {
|
|
stack.push([d, s]);
|
|
}
|
|
}
|
|
}
|
|
addBatchFunc(batch, "H", () => {
|
|
const changedAtoms = /* @__PURE__ */ new Set([atom]);
|
|
for (let i = topSortedReversed.length - 1; i >= 0; --i) {
|
|
const [a, aState, prevEpochNumber] = topSortedReversed[i];
|
|
let hasChangedDeps = false;
|
|
for (const dep of aState.d.keys()) {
|
|
if (dep !== a && changedAtoms.has(dep)) {
|
|
hasChangedDeps = true;
|
|
break;
|
|
}
|
|
}
|
|
if (hasChangedDeps) {
|
|
readAtomState(batch, a);
|
|
mountDependencies(batch, a, aState);
|
|
if (prevEpochNumber !== aState.n) {
|
|
registerBatchAtom(batch, a, aState);
|
|
changedAtoms.add(a);
|
|
}
|
|
}
|
|
delete aState.x;
|
|
}
|
|
});
|
|
};
|
|
const writeAtomState = (batch, atom, ...args) => {
|
|
let isSync = true;
|
|
const getter = (a) => returnAtomValue(readAtomState(batch, a));
|
|
const setter = (a, ...args2) => {
|
|
const aState = getAtomState(a);
|
|
try {
|
|
if (isSelfAtom(atom, a)) {
|
|
if (!hasInitialValue(a)) {
|
|
throw new Error("atom not writable");
|
|
}
|
|
const prevEpochNumber = aState.n;
|
|
const v = args2[0];
|
|
setAtomStateValueOrPromise(a, aState, v);
|
|
mountDependencies(batch, a, aState);
|
|
if (prevEpochNumber !== aState.n) {
|
|
registerBatchAtom(batch, a, aState);
|
|
recomputeDependents(batch, a, aState);
|
|
}
|
|
return void 0;
|
|
} else {
|
|
return writeAtomState(batch, a, ...args2);
|
|
}
|
|
} finally {
|
|
if (!isSync) {
|
|
flushBatch(batch);
|
|
}
|
|
}
|
|
};
|
|
try {
|
|
return atomWrite(atom, getter, setter, ...args);
|
|
} finally {
|
|
isSync = false;
|
|
}
|
|
};
|
|
const writeAtom = (atom, ...args) => {
|
|
const batch = createBatch();
|
|
try {
|
|
return writeAtomState(batch, atom, ...args);
|
|
} finally {
|
|
flushBatch(batch);
|
|
}
|
|
};
|
|
const mountDependencies = (batch, atom, atomState) => {
|
|
if (atomState.m && !isPendingPromise(atomState.v)) {
|
|
for (const a of atomState.d.keys()) {
|
|
if (!atomState.m.d.has(a)) {
|
|
const aMounted = mountAtom(batch, a, getAtomState(a));
|
|
aMounted.t.add(atom);
|
|
atomState.m.d.add(a);
|
|
}
|
|
}
|
|
for (const a of atomState.m.d || []) {
|
|
if (!atomState.d.has(a)) {
|
|
atomState.m.d.delete(a);
|
|
const aMounted = unmountAtom(batch, a, getAtomState(a));
|
|
aMounted == null ? void 0 : aMounted.t.delete(atom);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
const mountAtom = (batch, atom, atomState) => {
|
|
if (!atomState.m) {
|
|
readAtomState(batch, atom);
|
|
for (const a of atomState.d.keys()) {
|
|
const aMounted = mountAtom(batch, a, getAtomState(a));
|
|
aMounted.t.add(atom);
|
|
}
|
|
atomState.m = {
|
|
l: /* @__PURE__ */ new Set(),
|
|
d: new Set(atomState.d.keys()),
|
|
t: /* @__PURE__ */ new Set()
|
|
};
|
|
if (isActuallyWritableAtom(atom)) {
|
|
const mounted = atomState.m;
|
|
let setAtom;
|
|
const createInvocationContext = (batch2, fn) => {
|
|
let isSync = true;
|
|
setAtom = (...args) => {
|
|
try {
|
|
return writeAtomState(batch2, atom, ...args);
|
|
} finally {
|
|
if (!isSync) {
|
|
flushBatch(batch2);
|
|
}
|
|
}
|
|
};
|
|
try {
|
|
return fn();
|
|
} finally {
|
|
isSync = false;
|
|
}
|
|
};
|
|
addBatchFunc(batch, "L", () => {
|
|
const onUnmount = createInvocationContext(
|
|
batch,
|
|
() => atomOnMount(atom, (...args) => setAtom(...args))
|
|
);
|
|
if (onUnmount) {
|
|
mounted.u = (batch2) => createInvocationContext(batch2, onUnmount);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
return atomState.m;
|
|
};
|
|
const unmountAtom = (batch, atom, atomState) => {
|
|
if (atomState.m && !atomState.m.l.size && !Array.from(atomState.m.t).some((a) => {
|
|
var _a;
|
|
return (_a = getAtomState(a).m) == null ? void 0 : _a.d.has(atom);
|
|
})) {
|
|
const onUnmount = atomState.m.u;
|
|
if (onUnmount) {
|
|
addBatchFunc(batch, "L", () => onUnmount(batch));
|
|
}
|
|
delete atomState.m;
|
|
for (const a of atomState.d.keys()) {
|
|
const aMounted = unmountAtom(batch, a, getAtomState(a));
|
|
aMounted == null ? void 0 : aMounted.t.delete(atom);
|
|
}
|
|
return void 0;
|
|
}
|
|
return atomState.m;
|
|
};
|
|
const subscribeAtom = (atom, listener) => {
|
|
const batch = createBatch();
|
|
const atomState = getAtomState(atom);
|
|
const mounted = mountAtom(batch, atom, atomState);
|
|
const listeners = mounted.l;
|
|
listeners.add(listener);
|
|
flushBatch(batch);
|
|
return () => {
|
|
listeners.delete(listener);
|
|
const batch2 = createBatch();
|
|
unmountAtom(batch2, atom, atomState);
|
|
flushBatch(batch2);
|
|
};
|
|
};
|
|
const unstable_derive = (fn) => buildStore(...fn(getAtomState, atomRead, atomWrite, atomOnMount));
|
|
const store = {
|
|
get: readAtom,
|
|
set: writeAtom,
|
|
sub: subscribeAtom,
|
|
unstable_derive
|
|
};
|
|
return store;
|
|
};
|
|
const deriveDevStoreRev4 = (store) => {
|
|
const proxyAtomStateMap = /* @__PURE__ */ new WeakMap();
|
|
const debugMountedAtoms = /* @__PURE__ */ new Set();
|
|
let savedGetAtomState;
|
|
let inRestoreAtom = 0;
|
|
const derivedStore = store.unstable_derive(
|
|
(getAtomState, atomRead, atomWrite, atomOnMount) => {
|
|
savedGetAtomState = getAtomState;
|
|
return [
|
|
(atom) => {
|
|
let proxyAtomState = proxyAtomStateMap.get(atom);
|
|
if (!proxyAtomState) {
|
|
const atomState = getAtomState(atom);
|
|
proxyAtomState = new Proxy(atomState, {
|
|
set(target, prop, value) {
|
|
if (prop === "m") {
|
|
debugMountedAtoms.add(atom);
|
|
}
|
|
return Reflect.set(target, prop, value);
|
|
},
|
|
deleteProperty(target, prop) {
|
|
if (prop === "m") {
|
|
debugMountedAtoms.delete(atom);
|
|
}
|
|
return Reflect.deleteProperty(target, prop);
|
|
}
|
|
});
|
|
proxyAtomStateMap.set(atom, proxyAtomState);
|
|
}
|
|
return proxyAtomState;
|
|
},
|
|
atomRead,
|
|
(atom, getter, setter, ...args) => {
|
|
if (inRestoreAtom) {
|
|
return setter(atom, ...args);
|
|
}
|
|
return atomWrite(atom, getter, setter, ...args);
|
|
},
|
|
atomOnMount
|
|
];
|
|
}
|
|
);
|
|
const savedStoreSet = derivedStore.set;
|
|
const devStore = {
|
|
// store dev methods (these are tentative and subject to change without notice)
|
|
dev4_get_internal_weak_map: () => ({
|
|
get: (atom) => {
|
|
const atomState = savedGetAtomState(atom);
|
|
if (atomState.n === 0) {
|
|
return void 0;
|
|
}
|
|
return atomState;
|
|
}
|
|
}),
|
|
dev4_get_mounted_atoms: () => debugMountedAtoms,
|
|
dev4_restore_atoms: (values) => {
|
|
const restoreAtom = {
|
|
read: () => null,
|
|
write: (_get, set) => {
|
|
++inRestoreAtom;
|
|
try {
|
|
for (const [atom, value] of values) {
|
|
if (hasInitialValue(atom)) {
|
|
set(atom, value);
|
|
}
|
|
}
|
|
} finally {
|
|
--inRestoreAtom;
|
|
}
|
|
}
|
|
};
|
|
savedStoreSet(restoreAtom);
|
|
}
|
|
};
|
|
return Object.assign(derivedStore, devStore);
|
|
};
|
|
const createStore = exports("createStore", () => {
|
|
const atomStateMap = /* @__PURE__ */ new WeakMap();
|
|
const getAtomState = (atom) => {
|
|
if (!atom) {
|
|
throw new Error("Atom is undefined or null");
|
|
}
|
|
let atomState = atomStateMap.get(atom);
|
|
if (!atomState) {
|
|
atomState = { d: /* @__PURE__ */ new Map(), p: /* @__PURE__ */ new Set(), n: 0 };
|
|
atomStateMap.set(atom, atomState);
|
|
}
|
|
return atomState;
|
|
};
|
|
const store = buildStore(
|
|
getAtomState,
|
|
(atom, ...params) => atom.read(...params),
|
|
(atom, ...params) => atom.write(...params),
|
|
(atom, ...params) => {
|
|
var _a;
|
|
return (_a = atom.onMount) == null ? void 0 : _a.call(atom, ...params);
|
|
}
|
|
);
|
|
{
|
|
return deriveDevStoreRev4(store);
|
|
}
|
|
});
|
|
let defaultStore;
|
|
const getDefaultStore = exports("getDefaultStore", () => {
|
|
if (!defaultStore) {
|
|
defaultStore = createStore();
|
|
{
|
|
globalThis.__JOTAI_DEFAULT_STORE__ || (globalThis.__JOTAI_DEFAULT_STORE__ = defaultStore);
|
|
if (globalThis.__JOTAI_DEFAULT_STORE__ !== defaultStore) {
|
|
console.warn(
|
|
"Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
return defaultStore;
|
|
});
|
|
|
|
})
|
|
};
|
|
}));
|