solid-js
Version:
A declarative JavaScript library for building user interfaces.
1,700 lines (1,691 loc) • 50.5 kB
JavaScript
let taskIdCounter = 1,
isCallbackScheduled = false,
isPerformingWork = false,
taskQueue = [],
currentTask = null,
shouldYieldToHost = null,
yieldInterval = 5,
deadline = 0,
maxYieldInterval = 300,
scheduleCallback = null,
scheduledCallback = null;
const maxSigned31BitInt = 1073741823;
function setupScheduler() {
const channel = new MessageChannel(),
port = channel.port2;
scheduleCallback = () => port.postMessage(null);
channel.port1.onmessage = () => {
if (scheduledCallback !== null) {
const currentTime = performance.now();
deadline = currentTime + yieldInterval;
const hasTimeRemaining = true;
try {
const hasMoreWork = scheduledCallback(hasTimeRemaining, currentTime);
if (!hasMoreWork) {
scheduledCallback = null;
} else port.postMessage(null);
} catch (error) {
port.postMessage(null);
throw error;
}
}
};
if (navigator && navigator.scheduling && navigator.scheduling.isInputPending) {
const scheduling = navigator.scheduling;
shouldYieldToHost = () => {
const currentTime = performance.now();
if (currentTime >= deadline) {
if (scheduling.isInputPending()) {
return true;
}
return currentTime >= maxYieldInterval;
} else {
return false;
}
};
} else {
shouldYieldToHost = () => performance.now() >= deadline;
}
}
function enqueue(taskQueue, task) {
function findIndex() {
let m = 0;
let n = taskQueue.length - 1;
while (m <= n) {
const k = n + m >> 1;
const cmp = task.expirationTime - taskQueue[k].expirationTime;
if (cmp > 0) m = k + 1;else if (cmp < 0) n = k - 1;else return k;
}
return m;
}
taskQueue.splice(findIndex(), 0, task);
}
function requestCallback(fn, options) {
if (!scheduleCallback) setupScheduler();
let startTime = performance.now(),
timeout = maxSigned31BitInt;
if (options && options.timeout) timeout = options.timeout;
const newTask = {
id: taskIdCounter++,
fn,
startTime,
expirationTime: startTime + timeout
};
enqueue(taskQueue, newTask);
if (!isCallbackScheduled && !isPerformingWork) {
isCallbackScheduled = true;
scheduledCallback = flushWork;
scheduleCallback();
}
return newTask;
}
function cancelCallback(task) {
task.fn = null;
}
function flushWork(hasTimeRemaining, initialTime) {
isCallbackScheduled = false;
isPerformingWork = true;
try {
return workLoop(hasTimeRemaining, initialTime);
} finally {
currentTask = null;
isPerformingWork = false;
}
}
function workLoop(hasTimeRemaining, initialTime) {
let currentTime = initialTime;
currentTask = taskQueue[0] || null;
while (currentTask !== null) {
if (currentTask.expirationTime > currentTime && (!hasTimeRemaining || shouldYieldToHost())) {
break;
}
const callback = currentTask.fn;
if (callback !== null) {
currentTask.fn = null;
const didUserCallbackTimeout = currentTask.expirationTime <= currentTime;
callback(didUserCallbackTimeout);
currentTime = performance.now();
if (currentTask === taskQueue[0]) {
taskQueue.shift();
}
} else taskQueue.shift();
currentTask = taskQueue[0] || null;
}
return currentTask !== null;
}
const sharedConfig = {};
function setHydrateContext(context) {
sharedConfig.context = context;
}
function nextHydrateContext() {
return {
...sharedConfig.context,
id: `${sharedConfig.context.id}${sharedConfig.context.count++}-`,
count: 0
};
}
const equalFn = (a, b) => a === b;
const $PROXY = Symbol("solid-proxy");
const $TRACK = Symbol("solid-track");
const $DEVCOMP = Symbol("solid-dev-component");
const signalOptions = {
equals: equalFn
};
let ERROR = null;
let runEffects = runQueue;
const STALE = 1;
const PENDING = 2;
const UNOWNED = {
owned: null,
cleanups: null,
context: null,
owner: null
};
const NO_INIT = {};
var Owner = null;
let Transition = null;
let Scheduler = null;
let ExternalSourceFactory = null;
let Listener = null;
let Updates = null;
let Effects = null;
let ExecCount = 0;
let rootCount = 0;
const [transPending, setTransPending] = /*@__PURE__*/createSignal(false);
function createRoot(fn, detachedOwner) {
const listener = Listener,
owner = Owner,
unowned = fn.length === 0,
root = unowned ? {
owned: null,
cleanups: null,
context: null,
owner: null
} : {
owned: null,
cleanups: null,
context: null,
owner: detachedOwner || owner
},
updateFn = unowned ? () => fn(() => {
throw new Error("Dispose method must be an explicit argument to createRoot function");
}) : () => fn(() => untrack(() => cleanNode(root)));
{
if (owner) root.name = `${owner.name}-r${rootCount++}`;
globalThis._$afterCreateRoot && globalThis._$afterCreateRoot(root);
}
Owner = root;
Listener = null;
try {
return runUpdates(updateFn, true);
} finally {
Listener = listener;
Owner = owner;
}
}
function createSignal(value, options) {
options = options ? Object.assign({}, signalOptions, options) : signalOptions;
const s = {
value,
observers: null,
observerSlots: null,
comparator: options.equals || undefined
};
if (!options.internal) s.name = registerGraph(options.name || hashValue(value), s);
const setter = value => {
if (typeof value === "function") {
if (Transition && Transition.running && Transition.sources.has(s)) value = value(s.tValue);else value = value(s.value);
}
return writeSignal(s, value);
};
return [readSignal.bind(s), setter];
}
function createComputed(fn, value, options) {
const c = createComputation(fn, value, true, STALE, options );
if (Scheduler && Transition && Transition.running) Updates.push(c);else updateComputation(c);
}
function createRenderEffect(fn, value, options) {
const c = createComputation(fn, value, false, STALE, options );
if (Scheduler && Transition && Transition.running) Updates.push(c);else updateComputation(c);
}
function createEffect(fn, value, options) {
runEffects = runUserEffects;
const c = createComputation(fn, value, false, STALE, options ),
s = SuspenseContext && lookup(Owner, SuspenseContext.id);
if (s) c.suspense = s;
c.user = true;
Effects ? Effects.push(c) : updateComputation(c);
}
function createReaction(onInvalidate, options) {
let fn;
const c = createComputation(() => {
fn ? fn() : untrack(onInvalidate);
fn = undefined;
}, undefined, false, 0, options ),
s = SuspenseContext && lookup(Owner, SuspenseContext.id);
if (s) c.suspense = s;
c.user = true;
return tracking => {
fn = tracking;
updateComputation(c);
};
}
function createMemo(fn, value, options) {
options = options ? Object.assign({}, signalOptions, options) : signalOptions;
const c = createComputation(fn, value, true, 0, options );
c.observers = null;
c.observerSlots = null;
c.comparator = options.equals || undefined;
if (Scheduler && Transition && Transition.running) {
c.tState = STALE;
Updates.push(c);
} else updateComputation(c);
return readSignal.bind(c);
}
function createResource(pSource, pFetcher, pOptions) {
let source;
let fetcher;
let options;
if (arguments.length === 2 && typeof pFetcher === "object" || arguments.length === 1) {
source = true;
fetcher = pSource;
options = pFetcher || {};
} else {
source = pSource;
fetcher = pFetcher;
options = pOptions || {};
}
let pr = null,
initP = NO_INIT,
id = null,
loadedUnderTransition = false,
scheduled = false,
resolved = ("initialValue" in options),
dynamic = typeof source === "function" && createMemo(source);
const contexts = new Set(),
[value, setValue] = (options.storage || createSignal)(options.initialValue),
[error, setError] = createSignal(undefined),
[track, trigger] = createSignal(undefined, {
equals: false
}),
[state, setState] = createSignal(resolved ? "ready" : "unresolved");
if (sharedConfig.context) {
id = `${sharedConfig.context.id}${sharedConfig.context.count++}`;
let v;
if (options.ssrLoadFrom === "initial") initP = options.initialValue;else if (sharedConfig.load && (v = sharedConfig.load(id))) initP = v[0];
}
function loadEnd(p, v, error, key) {
if (pr === p) {
pr = null;
resolved = true;
if ((p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
value: v
}));
initP = NO_INIT;
if (Transition && p && loadedUnderTransition) {
Transition.promises.delete(p);
loadedUnderTransition = false;
runUpdates(() => {
Transition.running = true;
completeLoad(v, error);
}, false);
} else completeLoad(v, error);
}
return v;
}
function completeLoad(v, err) {
runUpdates(() => {
if (!err) setValue(() => v);
setState(err ? "errored" : "ready");
setError(err);
for (const c of contexts.keys()) c.decrement();
contexts.clear();
}, false);
}
function read() {
const c = SuspenseContext && lookup(Owner, SuspenseContext.id),
v = value(),
err = error();
if (err && !pr) throw err;
if (Listener && !Listener.user && c) {
createComputed(() => {
track();
if (pr) {
if (c.resolved && Transition && loadedUnderTransition) Transition.promises.add(pr);else if (!contexts.has(c)) {
c.increment();
contexts.add(c);
}
}
});
}
return v;
}
function load(refetching = true) {
if (refetching !== false && scheduled) return;
scheduled = false;
const lookup = dynamic ? dynamic() : source;
loadedUnderTransition = Transition && Transition.running;
if (lookup == null || lookup === false) {
loadEnd(pr, untrack(value));
return;
}
if (Transition && pr) Transition.promises.delete(pr);
const p = initP !== NO_INIT ? initP : untrack(() => fetcher(lookup, {
value: value(),
refetching
}));
if (typeof p !== "object" || !(p && "then" in p)) {
loadEnd(pr, p, undefined, lookup);
return p;
}
pr = p;
scheduled = true;
queueMicrotask(() => scheduled = false);
runUpdates(() => {
setState(resolved ? "refreshing" : "pending");
trigger();
}, false);
return p.then(v => loadEnd(p, v, undefined, lookup), e => loadEnd(p, undefined, castError(e), lookup));
}
Object.defineProperties(read, {
state: {
get: () => state()
},
error: {
get: () => error()
},
loading: {
get() {
const s = state();
return s === "pending" || s === "refreshing";
}
},
latest: {
get() {
if (!resolved) return read();
const err = error();
if (err && !pr) throw err;
return value();
}
}
});
if (dynamic) createComputed(() => load(false));else load(false);
return [read, {
refetch: load,
mutate: setValue
}];
}
function createDeferred(source, options) {
let t,
timeout = options ? options.timeoutMs : undefined;
const node = createComputation(() => {
if (!t || !t.fn) t = requestCallback(() => setDeferred(() => node.value), timeout !== undefined ? {
timeout
} : undefined);
return source();
}, undefined, true);
const [deferred, setDeferred] = createSignal(node.value, options);
updateComputation(node);
setDeferred(() => node.value);
return deferred;
}
function createSelector(source, fn = equalFn, options) {
const subs = new Map();
const node = createComputation(p => {
const v = source();
for (const [key, val] of subs.entries()) if (fn(key, v) !== fn(key, p)) {
for (const c of val.values()) {
c.state = STALE;
if (c.pure) Updates.push(c);else Effects.push(c);
}
}
return v;
}, undefined, true, STALE, options );
updateComputation(node);
return key => {
const listener = Listener;
if (listener) {
let l;
if (l = subs.get(key)) l.add(listener);else subs.set(key, l = new Set([listener]));
onCleanup(() => {
l.delete(listener);
!l.size && subs.delete(key);
});
}
return fn(key, Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value);
};
}
function batch(fn) {
return runUpdates(fn, false);
}
function untrack(fn) {
const listener = Listener;
Listener = null;
try {
return fn();
} finally {
Listener = listener;
}
}
function on(deps, fn, options) {
const isArray = Array.isArray(deps);
let prevInput;
let defer = options && options.defer;
return prevValue => {
let input;
if (isArray) {
input = Array(deps.length);
for (let i = 0; i < deps.length; i++) input[i] = deps[i]();
} else input = deps();
if (defer) {
defer = false;
return undefined;
}
const result = untrack(() => fn(input, prevInput, prevValue));
prevInput = input;
return result;
};
}
function onMount(fn) {
createEffect(() => untrack(fn));
}
function onCleanup(fn) {
if (Owner === null) console.warn("cleanups created outside a `createRoot` or `render` will never be run");else if (Owner.cleanups === null) Owner.cleanups = [fn];else Owner.cleanups.push(fn);
return fn;
}
function onError(fn) {
ERROR || (ERROR = Symbol("error"));
if (Owner === null) console.warn("error handlers created outside a `createRoot` or `render` will never be run");else if (Owner.context === null) Owner.context = {
[ERROR]: [fn]
};else if (!Owner.context[ERROR]) Owner.context[ERROR] = [fn];else Owner.context[ERROR].push(fn);
}
function getListener() {
return Listener;
}
function getOwner() {
return Owner;
}
function runWithOwner(o, fn) {
const prev = Owner;
Owner = o;
try {
return runUpdates(fn, true);
} catch (err) {
handleError(err);
} finally {
Owner = prev;
}
}
function enableScheduling(scheduler = requestCallback) {
Scheduler = scheduler;
}
function startTransition(fn) {
if (Transition && Transition.running) {
fn();
return Transition.done;
}
const l = Listener;
const o = Owner;
return Promise.resolve().then(() => {
Listener = l;
Owner = o;
let t;
if (Scheduler || SuspenseContext) {
t = Transition || (Transition = {
sources: new Set(),
effects: [],
promises: new Set(),
disposed: new Set(),
queue: new Set(),
running: true
});
t.done || (t.done = new Promise(res => t.resolve = res));
t.running = true;
}
runUpdates(fn, false);
Listener = Owner = null;
return t ? t.done : undefined;
});
}
function useTransition() {
return [transPending, startTransition];
}
function resumeEffects(e) {
Effects.push.apply(Effects, e);
e.length = 0;
}
function devComponent(Comp, props) {
const c = createComputation(() => untrack(() => {
Object.assign(Comp, {
[$DEVCOMP]: true
});
return Comp(props);
}), undefined, true, 0);
c.props = props;
c.observers = null;
c.observerSlots = null;
c.componentName = Comp.name;
updateComputation(c);
return c.tValue !== undefined ? c.tValue : c.value;
}
function hashValue(v) {
const s = new Set();
return `s${typeof v === "string" ? hash(v) : hash(untrack(() => JSON.stringify(v, (k, v) => {
if (typeof v === "object" && v != null) {
if (s.has(v)) return;
s.add(v);
const keys = Object.keys(v);
const desc = Object.getOwnPropertyDescriptors(v);
const newDesc = keys.reduce((memo, key) => {
const value = desc[key];
if (!value.get) memo[key] = value;
return memo;
}, {});
v = Object.create({}, newDesc);
}
if (typeof v === "bigint") {
return `${v.toString()}n`;
}
return v;
}) || ""))}`;
}
function registerGraph(name, value) {
let tryName = name;
if (Owner) {
let i = 0;
Owner.sourceMap || (Owner.sourceMap = {});
while (Owner.sourceMap[tryName]) tryName = `${name}-${++i}`;
Owner.sourceMap[tryName] = value;
value.graph = Owner;
}
return tryName;
}
function serializeGraph(owner) {
owner || (owner = Owner);
if (!owner) return {};
return {
...serializeValues(owner.sourceMap),
...(owner.owned ? serializeChildren(owner) : {})
};
}
function createContext(defaultValue, options) {
const id = Symbol("context");
return {
id,
Provider: createProvider(id, options),
defaultValue
};
}
function useContext(context) {
let ctx;
return (ctx = lookup(Owner, context.id)) !== undefined ? ctx : context.defaultValue;
}
function children(fn) {
const children = createMemo(fn);
const memo = createMemo(() => resolveChildren(children()), undefined, {
name: "children"
}) ;
memo.toArray = () => {
const c = memo();
return Array.isArray(c) ? c : c != null ? [c] : [];
};
return memo;
}
let SuspenseContext;
function getSuspenseContext() {
return SuspenseContext || (SuspenseContext = createContext({}));
}
function enableExternalSource(factory) {
if (ExternalSourceFactory) {
const oldFactory = ExternalSourceFactory;
ExternalSourceFactory = (fn, trigger) => {
const oldSource = oldFactory(fn, trigger);
const source = factory(x => oldSource.track(x), trigger);
return {
track: x => source.track(x),
dispose() {
source.dispose();
oldSource.dispose();
}
};
};
} else {
ExternalSourceFactory = factory;
}
}
function readSignal() {
const runningTransition = Transition && Transition.running;
if (this.sources && (!runningTransition && this.state || runningTransition && this.tState)) {
if (!runningTransition && this.state === STALE || runningTransition && this.tState === STALE) updateComputation(this);else {
const updates = Updates;
Updates = null;
runUpdates(() => lookUpstream(this), false);
Updates = updates;
}
}
if (Listener) {
const sSlot = this.observers ? this.observers.length : 0;
if (!Listener.sources) {
Listener.sources = [this];
Listener.sourceSlots = [sSlot];
} else {
Listener.sources.push(this);
Listener.sourceSlots.push(sSlot);
}
if (!this.observers) {
this.observers = [Listener];
this.observerSlots = [Listener.sources.length - 1];
} else {
this.observers.push(Listener);
this.observerSlots.push(Listener.sources.length - 1);
}
}
if (runningTransition && Transition.sources.has(this)) return this.tValue;
return this.value;
}
function writeSignal(node, value, isComp) {
let current = Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value;
if (!node.comparator || !node.comparator(current, value)) {
if (Transition) {
const TransitionRunning = Transition.running;
if (TransitionRunning || !isComp && Transition.sources.has(node)) {
Transition.sources.add(node);
node.tValue = value;
}
if (!TransitionRunning) node.value = value;
} else node.value = value;
if (node.observers && node.observers.length) {
runUpdates(() => {
for (let i = 0; i < node.observers.length; i += 1) {
const o = node.observers[i];
const TransitionRunning = Transition && Transition.running;
if (TransitionRunning && Transition.disposed.has(o)) continue;
if (TransitionRunning && !o.tState || !TransitionRunning && !o.state) {
if (o.pure) Updates.push(o);else Effects.push(o);
if (o.observers) markDownstream(o);
}
if (TransitionRunning) o.tState = STALE;else o.state = STALE;
}
if (Updates.length > 10e5) {
Updates = [];
if ("_SOLID_DEV_") throw new Error("Potential Infinite Loop Detected.");
throw new Error();
}
}, false);
}
}
return value;
}
function updateComputation(node) {
if (!node.fn) return;
cleanNode(node);
const owner = Owner,
listener = Listener,
time = ExecCount;
Listener = Owner = node;
runComputation(node, Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value, time);
if (Transition && !Transition.running && Transition.sources.has(node)) {
queueMicrotask(() => {
runUpdates(() => {
Transition && (Transition.running = true);
Listener = Owner = node;
runComputation(node, node.tValue, time);
Listener = Owner = null;
}, false);
});
}
Listener = listener;
Owner = owner;
}
function runComputation(node, value, time) {
let nextValue;
try {
nextValue = node.fn(value);
} catch (err) {
if (node.pure) {
if (Transition && Transition.running) {
node.tState = STALE;
node.tOwned && node.tOwned.forEach(cleanNode);
node.tOwned = undefined;
} else {
node.state = STALE;
node.owned && node.owned.forEach(cleanNode);
node.owned = null;
}
}
handleError(err);
}
if (!node.updatedAt || node.updatedAt <= time) {
if (node.updatedAt != null && "observers" in node) {
writeSignal(node, nextValue, true);
} else if (Transition && Transition.running && node.pure) {
Transition.sources.add(node);
node.tValue = nextValue;
} else node.value = nextValue;
node.updatedAt = time;
}
}
function createComputation(fn, init, pure, state = STALE, options) {
const c = {
fn,
state: state,
updatedAt: null,
owned: null,
sources: null,
sourceSlots: null,
cleanups: null,
value: init,
owner: Owner,
context: null,
pure
};
if (Transition && Transition.running) {
c.state = 0;
c.tState = state;
}
if (Owner === null) console.warn("computations created outside a `createRoot` or `render` will never be disposed");else if (Owner !== UNOWNED) {
if (Transition && Transition.running && Owner.pure) {
if (!Owner.tOwned) Owner.tOwned = [c];else Owner.tOwned.push(c);
} else {
if (!Owner.owned) Owner.owned = [c];else Owner.owned.push(c);
}
c.name = options && options.name || `${Owner.name || "c"}-${(Owner.owned || Owner.tOwned).length}`;
}
if (ExternalSourceFactory) {
const [track, trigger] = createSignal(undefined, {
equals: false
});
const ordinary = ExternalSourceFactory(c.fn, trigger);
onCleanup(() => ordinary.dispose());
const triggerInTransition = () => startTransition(trigger).then(() => inTransition.dispose());
const inTransition = ExternalSourceFactory(c.fn, triggerInTransition);
c.fn = x => {
track();
return Transition && Transition.running ? inTransition.track(x) : ordinary.track(x);
};
}
return c;
}
function runTop(node) {
const runningTransition = Transition && Transition.running;
if (!runningTransition && node.state === 0 || runningTransition && node.tState === 0) return;
if (!runningTransition && node.state === PENDING || runningTransition && node.tState === PENDING) return lookUpstream(node);
if (node.suspense && untrack(node.suspense.inFallback)) return node.suspense.effects.push(node);
const ancestors = [node];
while ((node = node.owner) && (!node.updatedAt || node.updatedAt < ExecCount)) {
if (runningTransition && Transition.disposed.has(node)) return;
if (!runningTransition && node.state || runningTransition && node.tState) ancestors.push(node);
}
for (let i = ancestors.length - 1; i >= 0; i--) {
node = ancestors[i];
if (runningTransition) {
let top = node,
prev = ancestors[i + 1];
while ((top = top.owner) && top !== prev) {
if (Transition.disposed.has(top)) return;
}
}
if (!runningTransition && node.state === STALE || runningTransition && node.tState === STALE) {
updateComputation(node);
} else if (!runningTransition && node.state === PENDING || runningTransition && node.tState === PENDING) {
const updates = Updates;
Updates = null;
runUpdates(() => lookUpstream(node, ancestors[0]), false);
Updates = updates;
}
}
}
function runUpdates(fn, init) {
if (Updates) return fn();
let wait = false;
if (!init) Updates = [];
if (Effects) wait = true;else Effects = [];
ExecCount++;
try {
const res = fn();
completeUpdates(wait);
return res;
} catch (err) {
if (!Updates) Effects = null;
handleError(err);
}
}
function completeUpdates(wait) {
if (Updates) {
if (Scheduler && Transition && Transition.running) scheduleQueue(Updates);else runQueue(Updates);
Updates = null;
}
if (wait) return;
let res;
if (Transition) {
if (!Transition.promises.size && !Transition.queue.size) {
const sources = Transition.sources;
const disposed = Transition.disposed;
Effects.push.apply(Effects, Transition.effects);
res = Transition.resolve;
for (const e of Effects) {
"tState" in e && (e.state = e.tState);
delete e.tState;
}
Transition = null;
runUpdates(() => {
for (const d of disposed) cleanNode(d);
for (const v of sources) {
v.value = v.tValue;
if (v.owned) {
for (let i = 0, len = v.owned.length; i < len; i++) cleanNode(v.owned[i]);
}
if (v.tOwned) v.owned = v.tOwned;
delete v.tValue;
delete v.tOwned;
v.tState = 0;
}
setTransPending(false);
}, false);
} else if (Transition.running) {
Transition.running = false;
Transition.effects.push.apply(Transition.effects, Effects);
Effects = null;
setTransPending(true);
return;
}
}
const e = Effects;
Effects = null;
if (e.length) runUpdates(() => runEffects(e), false);else globalThis._$afterUpdate && globalThis._$afterUpdate();
if (res) res();
}
function runQueue(queue) {
for (let i = 0; i < queue.length; i++) runTop(queue[i]);
}
function scheduleQueue(queue) {
for (let i = 0; i < queue.length; i++) {
const item = queue[i];
const tasks = Transition.queue;
if (!tasks.has(item)) {
tasks.add(item);
Scheduler(() => {
tasks.delete(item);
runUpdates(() => {
Transition.running = true;
runTop(item);
}, false);
Transition && (Transition.running = false);
});
}
}
}
function runUserEffects(queue) {
let i,
userLength = 0;
for (i = 0; i < queue.length; i++) {
const e = queue[i];
if (!e.user) runTop(e);else queue[userLength++] = e;
}
if (sharedConfig.context) setHydrateContext();
for (i = 0; i < userLength; i++) runTop(queue[i]);
}
function lookUpstream(node, ignore) {
const runningTransition = Transition && Transition.running;
if (runningTransition) node.tState = 0;else node.state = 0;
for (let i = 0; i < node.sources.length; i += 1) {
const source = node.sources[i];
if (source.sources) {
if (!runningTransition && source.state === STALE || runningTransition && source.tState === STALE) {
if (source !== ignore) runTop(source);
} else if (!runningTransition && source.state === PENDING || runningTransition && source.tState === PENDING) lookUpstream(source, ignore);
}
}
}
function markDownstream(node) {
const runningTransition = Transition && Transition.running;
for (let i = 0; i < node.observers.length; i += 1) {
const o = node.observers[i];
if (!runningTransition && !o.state || runningTransition && !o.tState) {
if (runningTransition) o.tState = PENDING;else o.state = PENDING;
if (o.pure) Updates.push(o);else Effects.push(o);
o.observers && markDownstream(o);
}
}
}
function cleanNode(node) {
let i;
if (node.sources) {
while (node.sources.length) {
const source = node.sources.pop(),
index = node.sourceSlots.pop(),
obs = source.observers;
if (obs && obs.length) {
const n = obs.pop(),
s = source.observerSlots.pop();
if (index < obs.length) {
n.sourceSlots[s] = index;
obs[index] = n;
source.observerSlots[index] = s;
}
}
}
}
if (Transition && Transition.running && node.pure) {
if (node.tOwned) {
for (i = 0; i < node.tOwned.length; i++) cleanNode(node.tOwned[i]);
delete node.tOwned;
}
reset(node, true);
} else if (node.owned) {
for (i = 0; i < node.owned.length; i++) cleanNode(node.owned[i]);
node.owned = null;
}
if (node.cleanups) {
for (i = 0; i < node.cleanups.length; i++) node.cleanups[i]();
node.cleanups = null;
}
if (Transition && Transition.running) node.tState = 0;else node.state = 0;
node.context = null;
delete node.sourceMap;
}
function reset(node, top) {
if (!top) {
node.tState = 0;
Transition.disposed.add(node);
}
if (node.owned) {
for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);
}
}
function castError(err) {
if (err instanceof Error || typeof err === "string") return err;
return new Error("Unknown error");
}
function handleError(err) {
err = castError(err);
const fns = ERROR && lookup(Owner, ERROR);
if (!fns) throw err;
for (const f of fns) f(err);
}
function lookup(owner, key) {
return owner ? owner.context && owner.context[key] !== undefined ? owner.context[key] : lookup(owner.owner, key) : undefined;
}
function resolveChildren(children) {
if (typeof children === "function" && !children.length) return resolveChildren(children());
if (Array.isArray(children)) {
const results = [];
for (let i = 0; i < children.length; i++) {
const result = resolveChildren(children[i]);
Array.isArray(result) ? results.push.apply(results, result) : results.push(result);
}
return results;
}
return children;
}
function createProvider(id, options) {
return function provider(props) {
let res;
createRenderEffect(() => res = untrack(() => {
Owner.context = {
[id]: props.value
};
return children(() => props.children);
}), undefined, options);
return res;
};
}
function hash(s) {
for (var i = 0, h = 9; i < s.length;) h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
return `${h ^ h >>> 9}`;
}
function serializeValues(sources = {}) {
const k = Object.keys(sources);
const result = {};
for (let i = 0; i < k.length; i++) {
const key = k[i];
result[key] = sources[key].value;
}
return result;
}
function serializeChildren(root) {
const result = {};
for (let i = 0, len = root.owned.length; i < len; i++) {
const node = root.owned[i];
result[node.componentName ? `${node.componentName}:${node.name}` : node.name] = {
...serializeValues(node.sourceMap),
...(node.owned ? serializeChildren(node) : {})
};
}
return result;
}
function observable(input) {
return {
subscribe(observer) {
if (!(observer instanceof Object) || observer == null) {
throw new TypeError("Expected the observer to be an object.");
}
const handler = typeof observer === "function" ? observer : observer.next && observer.next.bind(observer);
if (!handler) {
return {
unsubscribe() {}
};
}
const dispose = createRoot(disposer => {
createEffect(() => {
const v = input();
untrack(() => handler(v));
});
return disposer;
});
if (getOwner()) onCleanup(dispose);
return {
unsubscribe() {
dispose();
}
};
},
[Symbol.observable || "@@observable"]() {
return this;
}
};
}
function from(producer) {
const [s, set] = createSignal(undefined, {
equals: false
});
if ("subscribe" in producer) {
const unsub = producer.subscribe(v => set(() => v));
onCleanup(() => "unsubscribe" in unsub ? unsub.unsubscribe() : unsub());
} else {
const clean = producer(set);
onCleanup(clean);
}
return s;
}
const FALLBACK = Symbol("fallback");
function dispose(d) {
for (let i = 0; i < d.length; i++) d[i]();
}
function mapArray(list, mapFn, options = {}) {
let items = [],
mapped = [],
disposers = [],
len = 0,
indexes = mapFn.length > 1 ? [] : null;
onCleanup(() => dispose(disposers));
return () => {
let newItems = list() || [],
i,
j;
newItems[$TRACK];
return untrack(() => {
let newLen = newItems.length,
newIndices,
newIndicesNext,
temp,
tempdisposers,
tempIndexes,
start,
end,
newEnd,
item;
if (newLen === 0) {
if (len !== 0) {
dispose(disposers);
disposers = [];
items = [];
mapped = [];
len = 0;
indexes && (indexes = []);
}
if (options.fallback) {
items = [FALLBACK];
mapped[0] = createRoot(disposer => {
disposers[0] = disposer;
return options.fallback();
});
len = 1;
}
}
else if (len === 0) {
mapped = new Array(newLen);
for (j = 0; j < newLen; j++) {
items[j] = newItems[j];
mapped[j] = createRoot(mapper);
}
len = newLen;
} else {
temp = new Array(newLen);
tempdisposers = new Array(newLen);
indexes && (tempIndexes = new Array(newLen));
for (start = 0, end = Math.min(len, newLen); start < end && items[start] === newItems[start]; start++);
for (end = len - 1, newEnd = newLen - 1; end >= start && newEnd >= start && items[end] === newItems[newEnd]; end--, newEnd--) {
temp[newEnd] = mapped[end];
tempdisposers[newEnd] = disposers[end];
indexes && (tempIndexes[newEnd] = indexes[end]);
}
newIndices = new Map();
newIndicesNext = new Array(newEnd + 1);
for (j = newEnd; j >= start; j--) {
item = newItems[j];
i = newIndices.get(item);
newIndicesNext[j] = i === undefined ? -1 : i;
newIndices.set(item, j);
}
for (i = start; i <= end; i++) {
item = items[i];
j = newIndices.get(item);
if (j !== undefined && j !== -1) {
temp[j] = mapped[i];
tempdisposers[j] = disposers[i];
indexes && (tempIndexes[j] = indexes[i]);
j = newIndicesNext[j];
newIndices.set(item, j);
} else disposers[i]();
}
for (j = start; j < newLen; j++) {
if (j in temp) {
mapped[j] = temp[j];
disposers[j] = tempdisposers[j];
if (indexes) {
indexes[j] = tempIndexes[j];
indexes[j](j);
}
} else mapped[j] = createRoot(mapper);
}
mapped = mapped.slice(0, len = newLen);
items = newItems.slice(0);
}
return mapped;
});
function mapper(disposer) {
disposers[j] = disposer;
if (indexes) {
const [s, set] = createSignal(j, {
name: "index"
}) ;
indexes[j] = set;
return mapFn(newItems[j], s);
}
return mapFn(newItems[j]);
}
};
}
function indexArray(list, mapFn, options = {}) {
let items = [],
mapped = [],
disposers = [],
signals = [],
len = 0,
i;
onCleanup(() => dispose(disposers));
return () => {
const newItems = list() || [];
newItems[$TRACK];
return untrack(() => {
if (newItems.length === 0) {
if (len !== 0) {
dispose(disposers);
disposers = [];
items = [];
mapped = [];
len = 0;
signals = [];
}
if (options.fallback) {
items = [FALLBACK];
mapped[0] = createRoot(disposer => {
disposers[0] = disposer;
return options.fallback();
});
len = 1;
}
return mapped;
}
if (items[0] === FALLBACK) {
disposers[0]();
disposers = [];
items = [];
mapped = [];
len = 0;
}
for (i = 0; i < newItems.length; i++) {
if (i < items.length && items[i] !== newItems[i]) {
signals[i](() => newItems[i]);
} else if (i >= items.length) {
mapped[i] = createRoot(mapper);
}
}
for (; i < items.length; i++) {
disposers[i]();
}
len = signals.length = disposers.length = newItems.length;
items = newItems.slice(0);
return mapped = mapped.slice(0, len);
});
function mapper(disposer) {
disposers[i] = disposer;
const [s, set] = createSignal(newItems[i], {
name: "value"
}) ;
signals[i] = set;
return mapFn(s, i);
}
};
}
let hydrationEnabled = false;
function enableHydration() {
hydrationEnabled = true;
}
function createComponent(Comp, props) {
if (hydrationEnabled) {
if (sharedConfig.context) {
const c = sharedConfig.context;
setHydrateContext(nextHydrateContext());
const r = devComponent(Comp, props || {}) ;
setHydrateContext(c);
return r;
}
}
return devComponent(Comp, props || {});
}
function trueFn() {
return true;
}
const propTraps = {
get(_, property, receiver) {
if (property === $PROXY) return receiver;
return _.get(property);
},
has(_, property) {
if (property === $PROXY) return true;
return _.has(property);
},
set: trueFn,
deleteProperty: trueFn,
getOwnPropertyDescriptor(_, property) {
return {
configurable: true,
enumerable: true,
get() {
return _.get(property);
},
set: trueFn,
deleteProperty: trueFn
};
},
ownKeys(_) {
return _.keys();
}
};
function resolveSource(s) {
return !(s = typeof s === "function" ? s() : s) ? {} : s;
}
function mergeProps(...sources) {
let proxy = false;
for (let i = 0; i < sources.length; i++) {
const s = sources[i];
proxy = proxy || !!s && $PROXY in s;
sources[i] = typeof s === "function" ? (proxy = true, createMemo(s)) : s;
}
if (proxy) {
return new Proxy({
get(property) {
for (let i = sources.length - 1; i >= 0; i--) {
const v = resolveSource(sources[i])[property];
if (v !== undefined) return v;
}
},
has(property) {
for (let i = sources.length - 1; i >= 0; i--) {
if (property in resolveSource(sources[i])) return true;
}
return false;
},
keys() {
const keys = [];
for (let i = 0; i < sources.length; i++) keys.push(...Object.keys(resolveSource(sources[i])));
return [...new Set(keys)];
}
}, propTraps);
}
const target = {};
for (let i = sources.length - 1; i >= 0; i--) {
if (sources[i]) {
const descriptors = Object.getOwnPropertyDescriptors(sources[i]);
for (const key in descriptors) {
if (key in target) continue;
Object.defineProperty(target, key, {
enumerable: true,
get() {
for (let i = sources.length - 1; i >= 0; i--) {
const v = (sources[i] || {})[key];
if (v !== undefined) return v;
}
}
});
}
}
}
return target;
}
function splitProps(props, ...keys) {
const blocked = new Set(keys.flat());
if ($PROXY in props) {
const res = keys.map(k => {
return new Proxy({
get(property) {
return k.includes(property) ? props[property] : undefined;
},
has(property) {
return k.includes(property) && property in props;
},
keys() {
return k.filter(property => property in props);
}
}, propTraps);
});
res.push(new Proxy({
get(property) {
return blocked.has(property) ? undefined : props[property];
},
has(property) {
return blocked.has(property) ? false : property in props;
},
keys() {
return Object.keys(props).filter(k => !blocked.has(k));
}
}, propTraps));
return res;
}
const descriptors = Object.getOwnPropertyDescriptors(props);
keys.push(Object.keys(descriptors).filter(k => !blocked.has(k)));
return keys.map(k => {
const clone = {};
for (let i = 0; i < k.length; i++) {
const key = k[i];
if (!(key in props)) continue;
Object.defineProperty(clone, key, descriptors[key] ? descriptors[key] : {
get() {
return props[key];
},
set() {
return true;
},
enumerable: true
});
}
return clone;
});
}
function lazy(fn) {
let comp;
let p;
const wrap = props => {
const ctx = sharedConfig.context;
if (ctx) {
const [s, set] = createSignal();
(p || (p = fn())).then(mod => {
setHydrateContext(ctx);
set(() => mod.default);
setHydrateContext();
});
comp = s;
} else if (!comp) {
const [s] = createResource(() => (p || (p = fn())).then(mod => mod.default));
comp = s;
}
let Comp;
return createMemo(() => (Comp = comp()) && untrack(() => {
if ("_SOLID_DEV_") Object.assign(Comp, {
[$DEVCOMP]: true
});
if (!ctx) return Comp(props);
const c = sharedConfig.context;
setHydrateContext(ctx);
const r = Comp(props);
setHydrateContext(c);
return r;
}));
};
wrap.preload = () => p || ((p = fn()).then(mod => comp = () => mod.default), p);
return wrap;
}
let counter = 0;
function createUniqueId() {
const ctx = sharedConfig.context;
return ctx ? `${ctx.id}${ctx.count++}` : `cl-${counter++}`;
}
function For(props) {
const fallback = "fallback" in props && {
fallback: () => props.fallback
};
return createMemo(mapArray(() => props.each, props.children, fallback || undefined), undefined, {
name: "value"
}) ;
}
function Index(props) {
const fallback = "fallback" in props && {
fallback: () => props.fallback
};
return createMemo(indexArray(() => props.each, props.children, fallback || undefined), undefined, {
name: "value"
}) ;
}
function Show(props) {
let strictEqual = false;
const keyed = props.keyed;
const condition = createMemo(() => props.when, undefined, {
equals: (a, b) => strictEqual ? a === b : !a === !b,
name: "condition"
} );
return createMemo(() => {
const c = condition();
if (c) {
const child = props.children;
const fn = typeof child === "function" && child.length > 0;
strictEqual = keyed || fn;
return fn ? untrack(() => child(c)) : child;
}
return props.fallback;
}, undefined, {
name: "value"
} );
}
function Switch(props) {
let strictEqual = false;
let keyed = false;
const equals = (a, b) => a[0] === b[0] && (strictEqual ? a[1] === b[1] : !a[1] === !b[1]) && a[2] === b[2];
const conditions = children(() => props.children),
evalConditions = createMemo(() => {
let conds = conditions();
if (!Array.isArray(conds)) conds = [conds];
for (let i = 0; i < conds.length; i++) {
const c = conds[i].when;
if (c) {
keyed = !!conds[i].keyed;
return [i, c, conds[i]];
}
}
return [-1];
}, undefined, {
equals,
name: "eval conditions"
} );
return createMemo(() => {
const [index, when, cond] = evalConditions();
if (index < 0) return props.fallback;
const c = cond.children;
const fn = typeof c === "function" && c.length > 0;
strictEqual = keyed || fn;
return fn ? untrack(() => c(when)) : c;
}, undefined, {
name: "value"
} );
}
function Match(props) {
return props;
}
let Errors;
function resetErrorBoundaries() {
Errors && [...Errors].forEach(fn => fn());
}
function ErrorBoundary(props) {
let err;
let v;
if (sharedConfig.context && sharedConfig.load && (v = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count))) err = v[0];
const [errored, setErrored] = createSignal(err, {
name: "errored"
} );
Errors || (Errors = new Set());
Errors.add(setErrored);
onCleanup(() => Errors.delete(setErrored));
return createMemo(() => {
let e;
if (e = errored()) {
const f = props.fallback;
if ((typeof f !== "function" || f.length == 0)) console.error(e);
const res = typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored())) : f;
onError(setErrored);
return res;
}
onError(setErrored);
return props.children;
}, undefined, {
name: "value"
} );
}
const suspenseListEquals = (a, b) => a.showContent === b.showContent && a.showFallback === b.showFallback;
const SuspenseListContext = createContext();
function SuspenseList(props) {
let [wrapper, setWrapper] = createSignal(() => ({
inFallback: false
})),
show;
const listContext = useContext(SuspenseListContext);
const [registry, setRegistry] = createSignal([]);
if (listContext) {
show = listContext.register(createMemo(() => wrapper()().inFallback));
}
const resolved = createMemo(prev => {
const reveal = props.revealOrder,
tail = props.tail,
{
showContent = true,
showFallback = true
} = show ? show() : {},
reg = registry(),
reverse = reveal === "backwards";
if (reveal === "together") {
const all = reg.every(inFallback => !inFallback());
const res = reg.map(() => ({
showContent: all && showContent,
showFallback
}));
res.inFallback = !all;
return res;
}
let stop = false;
let inFallback = prev.inFallback;
const res = [];
for (let i = 0, len = reg.length; i < len; i++) {
const n = reverse ? len - i - 1 : i,
s = reg[n]();
if (!stop && !s) {
res[n] = {
showContent,
showFallback
};
} else {
const next = !stop;
if (next) inFallback = true;
res[n] = {
showContent: next,
showFallback: !tail || next && tail === "collapsed" ? showFallback : false
};
stop = true;
}
}
if (!stop) inFallback = false;
res.inFallback = inFallback;
return res;
}, {
inFallback: false
});
setWrapper(() => resolved);
return createComponent(SuspenseListContext.Provider, {
value: {
register: inFallback => {
let index;
setRegistry(registry => {
index = registry.length;
return [...registry, inFallback];
});
return createMemo(() => resolved()[index], undefined, {
equals: suspenseListEquals
});
}
},
get children() {
return props.children;
}
});
}
function Suspense(props) {
let counter = 0,
show,
ctx,
p,
flicker,
error;
const [inFallback, setFallback] = createSignal(false),
SuspenseContext = getSuspenseContext(),
store = {
increment: () => {
if (++counter === 1) setFallback(true);
},
decrement: () => {
if (--counter === 0) setFallback(false);
},
inFallback,
effects: [],
resolved: false
},
owner = getOwner();
if (sharedConfig.context && sharedConfig.load) {
const key = sharedConfig.context.id + sharedConfig.context.count;
let ref = sharedConfig.load(key);
if (ref && (p = ref[0]) && p !== "$$f") {
if (typeof p !== "object" || !("then" in p)) p = Promise.resolve(p);
const [s, set] = createSignal(undefined, {
equals: false
});
flicker = s;
p.then(err => {
if (err || sharedConfig.done) {
err && (error = err);
return set();
}
sharedConfig.gather(key);
setHydrateContext(ctx);
set();
setHydrateContext();
});
}
}
const listContext = useContext(SuspenseListContext);
if (listContext) show = listContext.register(store.inFallback);
let dispose;
onCleanup(() => dispose && dispose());
return createComponent(SuspenseContext.Provider, {
value: store,
get children() {
return createMemo(() => {
if (error) throw error;
ctx = sharedConfig.context;
if (flicker) {
flicker();
return flicker = undefined;
}
if (ctx && p === "$$f") setHydrateContext();
const rendered = createMemo(() => props.children);
return createMemo(prev => {
const inFallback = store.inFallback(),
{
showContent = true,
showFallback = true
} = show ? show() : {};
if ((!inFallback || p && p !== "$$f") && showContent) {
store.resolved = true;
dispose && dispose();
dispose = ctx = p = undefined;
resumeEffects(store.effects);
return rendered();
}
if (!showFallback) return;
if (dispose) return prev;
return createRoot(disposer => {
dispose = disposer;
if (ctx) {
setHydrateContext({
id: ctx.id + "f",
count: 0
});
ctx = undefined;
}
return props.fallback;
}, owner);
});
});
}
});
}
let DEV;
{
DEV = {
writeSignal,
serializeGraph,
registerGraph,
hashValue
};
}
if (globalThis) {
if (!globalThis.Solid$$) globalThis.Solid$$ = true;else console.warn("You appear to have multiple instances of Solid. This can lead to unexpected behavior.");
}
export { $DEVCOMP, $PROXY, $TRACK, DEV, ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, batch, cancelCallback, children, createComponent, createComputed, createContex