solid-js
Version:
A declarative JavaScript library for building user interfaces.
1,345 lines (1,335 loc) • 38.7 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 signalOptions = {
equals: equalFn
};
let ERROR = null;
let runEffects = runQueue;
const NOTPENDING = {};
const STALE = 1;
const PENDING = 2;
const UNOWNED = {
owned: null,
cleanups: null,
context: null,
owner: null
};
const [transPending, setTransPending] = /*@__PURE__*/createSignal(false);
var Owner = null;
let Transition = null;
let Scheduler = null;
let Listener = null;
let Pending = null;
let Updates = null;
let Effects = null;
let ExecCount = 0;
function createRoot(fn, detachedOwner) {
detachedOwner && (Owner = detachedOwner);
const listener = Listener,
owner = Owner,
root = fn.length === 0 && !false ? UNOWNED : {
owned: null,
cleanups: null,
context: null,
owner
};
Owner = root;
Listener = null;
let result;
try {
runUpdates(() => result = fn(() => cleanNode(root)), true);
} finally {
Listener = listener;
Owner = owner;
}
return result;
}
function createSignal(value, options) {
options = options ? Object.assign({}, signalOptions, options) : signalOptions;
const s = {
value,
observers: null,
observerSlots: null,
pending: NOTPENDING,
comparator: options.equals || undefined
};
return [readSignal.bind(s), value => {
if (typeof value === "function") {
if (Transition && Transition.running && Transition.sources.has(s)) value = value(s.pending !== NOTPENDING ? s.pending : s.tValue);else value = value(s.pending !== NOTPENDING ? s.pending : s.value);
}
return writeSignal(s, value);
}];
}
function createComputed(fn, value, options) {
updateComputation(createComputation(fn, value, true, STALE));
}
function createRenderEffect(fn, value, options) {
updateComputation(createComputation(fn, value, false, STALE));
}
function createEffect(fn, value, options) {
runEffects = runUserEffects;
const c = createComputation(fn, value, false, STALE),
s = SuspenseContext && lookup(Owner, SuspenseContext.id);
if (s) c.suspense = s;
c.user = true;
Effects && Effects.push(c);
}
function createMemo(fn, value, options) {
options = options ? Object.assign({}, signalOptions, options) : signalOptions;
const c = createComputation(fn, value, true, 0);
c.pending = NOTPENDING;
c.observers = null;
c.observerSlots = null;
c.comparator = options.equals || undefined;
updateComputation(c);
return readSignal.bind(c);
}
function createResource(source, fetcher, options = {}) {
if (arguments.length === 2) {
if (typeof fetcher === "object") {
options = fetcher;
fetcher = source;
source = true;
}
} else if (arguments.length === 1) {
fetcher = source;
source = true;
}
const contexts = new Set(),
[s, set] = createSignal(options.initialValue),
[track, trigger] = createSignal(undefined, {
equals: false
}),
[loading, setLoading] = createSignal(false),
[error, setError] = createSignal();
let err = undefined,
pr = null,
initP = null,
id = null,
loadedUnderTransition = false,
dynamic = typeof source === "function";
if (sharedConfig.context) {
id = `${sharedConfig.context.id}${sharedConfig.context.count++}`;
if (sharedConfig.context.loadResource) {
initP = sharedConfig.context.loadResource(id);
} else if (sharedConfig.resources && id && id in sharedConfig.resources) {
initP = sharedConfig.resources[id];
delete sharedConfig.resources[id];
}
}
function loadEnd(p, v, e) {
if (pr === p) {
setError(err = e);
pr = null;
if (Transition && p && loadedUnderTransition) {
Transition.promises.delete(p);
loadedUnderTransition = false;
runUpdates(() => {
Transition.running = true;
if (!Transition.promises.size) {
Effects.push.apply(Effects, Transition.effects);
Transition.effects = [];
}
completeLoad(v);
}, false);
} else completeLoad(v);
}
return v;
}
function completeLoad(v) {
batch(() => {
set(() => v);
setLoading(false);
for (const c of contexts.keys()) c.decrement();
contexts.clear();
});
}
function read() {
const c = SuspenseContext && lookup(Owner, SuspenseContext.id),
v = s();
if (err) throw err;
if (Listener && !Listener.user && c) {
createComputed(() => {
track();
if (pr) {
if (c.resolved && Transition) Transition.promises.add(pr);else if (!contexts.has(c)) {
c.increment();
contexts.add(c);
}
}
});
}
return v;
}
function load() {
setError(err = undefined);
const lookup = dynamic ? source() : source;
loadedUnderTransition = Transition && Transition.running;
if (lookup == null || lookup === false) {
loadEnd(pr, untrack(s));
return;
}
if (Transition && pr) Transition.promises.delete(pr);
const p = initP || untrack(() => fetcher(lookup, s));
initP = null;
if (typeof p !== "object" || !("then" in p)) {
loadEnd(pr, p);
return;
}
pr = p;
batch(() => {
setLoading(true);
trigger();
});
p.then(v => loadEnd(p, v), e => loadEnd(p, e, e));
}
Object.defineProperties(read, {
loading: {
get() {
return loading();
}
},
error: {
get() {
return error();
}
}
});
if (dynamic) createComputed(load);else load();
return [read, {
refetch: load,
mutate: set
}];
}
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 of subs.keys()) if (fn(key, v) || p !== undefined && fn(key, p)) {
const l = subs.get(key);
for (const c of l.values()) {
c.state = STALE;
if (c.pure) Updates.push(c);else Effects.push(c);
}
}
return v;
}, undefined, true, STALE);
updateComputation(node);
return key => {
let listener;
if (listener = Listener) {
let l;
if (l = subs.get(key)) l.add(listener);else subs.set(key, l = new Set([listener]));
onCleanup(() => {
l.size > 1 ? l.delete(listener) : subs.delete(key);
});
}
return fn(key, Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value);
};
}
function batch(fn) {
if (Pending) return fn();
let result;
const q = Pending = [];
try {
result = fn();
} finally {
Pending = null;
}
runUpdates(() => {
for (let i = 0; i < q.length; i += 1) {
const data = q[i];
if (data.pending !== NOTPENDING) {
const pending = data.pending;
data.pending = NOTPENDING;
writeSignal(data, pending);
}
}
}, false);
return result;
}
function untrack(fn) {
let result,
listener = Listener;
Listener = null;
result = fn();
Listener = listener;
return result;
}
function on(deps, fn, options) {
const isArray = Array.isArray(deps);
let prevInput;
let defer = options && options.defer;
return prevValue => {
let input;
if (isArray) {
input = [];
for (let i = 0; i < deps.length; i++) input.push(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) ;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) ;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 fn();
} finally {
Owner = prev;
}
}
function enableScheduling(scheduler = requestCallback) {
Scheduler = scheduler;
}
function startTransition(fn, cb) {
if (Scheduler || SuspenseContext) {
Transition || (Transition = {
sources: new Set(),
effects: [],
promises: new Set(),
disposed: new Set(),
queue: new Set(),
running: true,
cb: []
});
cb && Transition.cb.push(cb);
Transition.running = true;
}
batch(fn);
if (!Scheduler && !SuspenseContext && cb) cb();
}
function useTransition() {
return [transPending, startTransition];
}
function resumeEffects(e) {
Transition && (Transition.running = true);
Effects.push.apply(Effects, e);
e.length = 0;
}
function createContext(defaultValue) {
const id = Symbol("context");
return {
id,
Provider: createProvider(id),
defaultValue
};
}
function useContext(context) {
return lookup(Owner, context.id) || context.defaultValue;
}
function children(fn) {
const children = createMemo(fn);
return createMemo(() => resolveChildren(children()));
}
let SuspenseContext;
function getSuspenseContext() {
return SuspenseContext || (SuspenseContext = createContext({}));
}
function readSignal() {
if (this.state && this.sources) {
const updates = Updates;
Updates = null;
this.state === STALE || Transition && Transition.running && this.tState ? updateComputation(this) : lookDownstream(this);
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 (Transition && Transition.running && Transition.sources.has(this)) return this.tValue;
return this.value;
}
function writeSignal(node, value, isComp) {
if (node.comparator) {
if (Transition && Transition.running && Transition.sources.has(node)) {
if (node.comparator(node.tValue, value)) return value;
} else if (node.comparator(node.value, value)) return value;
}
if (Pending) {
if (node.pending === NOTPENDING) Pending.push(node);
node.pending = value;
return value;
}
let TransitionRunning = false;
if (Transition) {
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];
if (TransitionRunning && Transition.disposed.has(o)) continue;
if (o.pure) Updates.push(o);else Effects.push(o);
if (o.observers && (TransitionRunning && !o.tState || !TransitionRunning && !o.state)) markUpstream(o);
if (TransitionRunning) o.tState = STALE;else o.state = STALE;
}
if (Updates.length > 10e5) {
Updates = [];
if (false) ;
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, node.value, time);
if (Transition && !Transition.running && Transition.sources.has(node)) {
Transition.running = true;
runComputation(node, node.tValue, time);
Transition.running = false;
}
Listener = listener;
Owner = owner;
}
function runComputation(node, value, time) {
let nextValue;
try {
nextValue = node.fn(value);
} catch (err) {
handleError(err);
}
if (!node.updatedAt || node.updatedAt <= time) {
if (node.observers && node.observers.length) {
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) ;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);
}
}
return c;
}
function runTop(node) {
const runningTransition = Transition && Transition.running;
if (!runningTransition && node.state !== STALE) return node.state = 0;
if (runningTransition && node.tState !== STALE) return node.tState = 0;
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 (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 (node.state === STALE || runningTransition && node.tState) {
updateComputation(node);
} else if (node.state === PENDING) {
const updates = Updates;
Updates = null;
lookDownstream(node);
Updates = updates;
}
}
}
function runUpdates(fn, init) {
if (Updates) return fn();
let wait = false;
if (!init) Updates = [];
if (Effects) wait = true;else Effects = [];
ExecCount++;
try {
fn();
} catch (err) {
handleError(err);
} finally {
completeUpdates(wait);
}
}
function completeUpdates(wait) {
if (Updates) {
if (Scheduler && Transition && Transition.running) scheduleQueue(Updates);else runQueue(Updates);
Updates = null;
}
if (wait) return;
let cbs;
if (Transition && Transition.running) {
if (Transition.promises.size || Transition.queue.size) {
Transition.running = false;
Transition.effects.push.apply(Transition.effects, Effects);
Effects = null;
setTransPending(true);
return;
}
const sources = Transition.sources;
cbs = Transition.cb;
Effects.forEach(e => {
e.state = STALE;
delete e.tState;
});
Transition = null;
batch(() => {
sources.forEach(v => {
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);
});
}
if (Effects.length) batch(() => {
runEffects(Effects);
Effects = null;
});else {
Effects = null;
}
if (cbs) cbs.forEach(cb => cb());
}
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);
if (!tasks.size) {
Effects.push.apply(Effects, Transition.effects);
Transition.effects = [];
}
}, 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;
}
const resume = queue.length;
for (i = 0; i < userLength; i++) runTop(queue[i]);
for (i = resume; i < queue.length; i++) runTop(queue[i]);
}
function lookDownstream(node) {
node.state = 0;
for (let i = 0; i < node.sources.length; i += 1) {
const source = node.sources[i];
if (source.sources) {
if (source.state === STALE || Transition && Transition.running && source.tState) runTop(source);else if (source.state === PENDING) lookDownstream(source);
}
}
}
function markUpstream(node) {
const runningTransition = Transition && Transition.running;
for (let i = 0; i < node.observers.length; i += 1) {
const o = node.observers[i];
if (!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 && markUpstream(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;
}
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 handleError(err) {
const fns = ERROR && lookup(Owner, ERROR);
if (!fns) throw err;
fns.forEach(f => f(err));
}
function lookup(owner, key) {
return owner && (owner.context && owner.context[key] || owner.owner && lookup(owner.owner, key));
}
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) {
return function provider(props) {
let res;
createComputed(() => res = untrack(() => {
Owner.context = {
[id]: props.value
};
return children(() => props.children);
}));
return res;
};
}
function getSymbol() {
const SymbolCopy = Symbol;
return SymbolCopy.observable || "@@observable";
}
function observable(input) {
const $$observable = getSymbol();
return {
subscribe(observer) {
if (!(observer instanceof Object) || observer == null) {
throw new TypeError("Expected the observer to be an object.");
}
const handler = "next" in observer ? observer.next : observer;
let complete = false;
createComputed(() => {
if (complete) return;
const v = input();
untrack(() => handler(v));
});
return {
unsubscribe() {
complete = true;
}
};
},
[$$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;
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);
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() || [];
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]);
signals[i] = set;
return mapFn(s, i);
}
};
}
function createComponent(Comp, props) {
if (sharedConfig.context) {
const c = sharedConfig.context;
setHydrateContext(nextHydrateContext());
const r = untrack(() => Comp(props));
setHydrateContext(c);
return r;
}
return untrack(() => Comp(props));
}
function trueFn() {
return true;
}
const propTraps = {
get(_, property, receiver) {
if (property === $PROXY) return receiver;
return _.get(property);
},
has(_, property) {
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 mergeProps(...sources) {
return new Proxy({
get(property) {
for (let i = sources.length - 1; i >= 0; i--) {
const v = sources[i][property];
if (v !== undefined) return v;
}
},
has(property) {
for (let i = sources.length - 1; i >= 0; i--) {
if (property in sources[i]) return true;
}
return false;
},
keys() {
const keys = [];
for (let i = 0; i < sources.length; i++) keys.push(...Object.keys(sources[i]));
return [...new Set(keys)];
}
}, propTraps);
}
function splitProps(props, ...keys) {
const blocked = new Set(keys.flat());
const descriptors = Object.getOwnPropertyDescriptors(props);
const res = keys.map(k => {
const clone = {};
for (let i = 0; i < k.length; i++) {
const key = k[i];
Object.defineProperty(clone, key, descriptors[key] ? descriptors[key] : {
get() {
return props[key];
}
});
}
return clone;
});
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;
}
function lazy(fn) {
let comp;
const wrap = props => {
const ctx = sharedConfig.context;
if (ctx && sharedConfig.resources) {
ctx.count++;
const [s, set] = createSignal();
fn().then(mod => {
setHydrateContext(ctx);
set(() => mod.default);
setHydrateContext(undefined);
});
comp = s;
} else if (!comp) {
const [s] = createResource(() => fn().then(mod => mod.default));
comp = s;
} else {
const c = comp();
if (c) return c(props);
}
let Comp;
return createMemo(() => (Comp = comp()) && untrack(() => {
if (!ctx) return Comp(props);
const c = sharedConfig.context;
setHydrateContext(ctx);
const r = Comp(props);
setHydrateContext(c);
return r;
}));
};
wrap.preload = () => comp || fn().then(mod => comp = () => mod.default);
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 ? fallback : undefined));
}
function Index(props) {
const fallback = "fallback" in props && {
fallback: () => props.fallback
};
return createMemo(indexArray(() => props.each, props.children, fallback ? fallback : undefined));
}
function Show(props) {
let strictEqual = false;
const condition = createMemo(() => props.when, undefined, {
equals: (a, b) => strictEqual ? a === b : !a === !b
});
return createMemo(() => {
const c = condition();
if (c) {
const child = props.children;
return (strictEqual = typeof child === "function" && child.length > 0) ? untrack(() => child(c)) : child;
}
return props.fallback;
});
}
function Switch(props) {
let strictEqual = false;
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) return [i, c, conds[i]];
}
return [-1];
}, undefined, {
equals: (a, b) => a && a[0] === b[0] && (strictEqual ? a[1] === b[1] : !a[1] === !b[1]) && a[2] === b[2]
});
return createMemo(() => {
const [index, when, cond] = evalConditions();
if (index < 0) return props.fallback;
const c = cond.children;
return (strictEqual = typeof c === "function" && c.length > 0) ? untrack(() => c(when)) : c;
});
}
function Match(props) {
return props;
}
function ErrorBoundary(props) {
const [errored, setErrored] = createSignal();
let e;
return createMemo(() => {
if ((e = errored()) != null) {
const f = props.fallback;
return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(null))) : f;
}
onError(setErrored);
return props.children;
});
}
const SuspenseListContext = createContext();
function SuspenseList(props) {
let index = 0,
suspenseSetter,
showContent,
showFallback;
const listContext = useContext(SuspenseListContext);
if (listContext) {
const [inFallback, setFallback] = createSignal(false);
suspenseSetter = setFallback;
[showContent, showFallback] = listContext.register(inFallback);
}
const registry = [],
comp = createComponent(SuspenseListContext.Provider, {
value: {
register: inFallback => {
const [showingContent, showContent] = createSignal(false),
[showingFallback, showFallback] = createSignal(false);
registry[index++] = {
inFallback,
showContent,
showFallback
};
return [showingContent, showingFallback];
}
},
get children() {
return props.children;
}
});
createComputed(() => {
const reveal = props.revealOrder,
tail = props.tail,
visibleContent = showContent ? showContent() : true,
visibleFallback = showFallback ? showFallback() : true,
reverse = reveal === "backwards";
if (reveal === "together") {
const all = registry.every(i => !i.inFallback());
suspenseSetter && suspenseSetter(!all);
registry.forEach(i => {
i.showContent(all && visibleContent);
i.showFallback(visibleFallback);
});
return;
}
let stop = false;
for (let i = 0, len = registry.length; i < len; i++) {
const n = reverse ? len - i - 1 : i,
s = registry[n].inFallback();
if (!stop && !s) {
registry[n].showContent(visibleContent);
registry[n].showFallback(visibleFallback);
} else {
const next = !stop;
if (next && suspenseSetter) suspenseSetter(true);
if (!tail || next && tail === "collapsed") {
registry[n].showFallback(visibleFallback);
} else registry[n].showFallback(false);
stop = true;
registry[n].showContent(next);
}
}
if (!stop && suspenseSetter) suspenseSetter(false);
});
return comp;
}
function Suspense(props) {
let counter = 0,
showContent,
showFallback;
const [inFallback, setFallback] = createSignal(false),
SuspenseContext = getSuspenseContext(),
store = {
increment: () => {
if (++counter === 1) setFallback(true);
},
decrement: () => {
if (--counter === 0) setFallback(false);
},
inFallback,
effects: [],
resolved: false
};
const listContext = useContext(SuspenseListContext);
if (listContext) [showContent, showFallback] = listContext.register(store.inFallback);
return createComponent(SuspenseContext.Provider, {
value: store,
get children() {
const rendered = untrack(() => props.children);
return createMemo(() => {
const inFallback = store.inFallback(),
visibleContent = showContent ? showContent() : true,
visibleFallback = showFallback ? showFallback() : true;
if (!inFallback && visibleContent) {
store.resolved = true;
resumeEffects(store.effects);
return rendered;
}
if (!visibleFallback) return;
return props.fallback;
});
}
});
}
function awaitSuspense() {}
let DEV;
export { $PROXY, DEV, ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, awaitSuspense, batch, cancelCallback, children, createComponent, createComputed, createContext, createDeferred, createEffect, createMemo, createRenderEffect, createResource, createRoot, createSelector, createSignal, createUniqueId, enableScheduling, equalFn, from, getListener, getOwner, indexArray, lazy, mapArray, mergeProps, observable, on, onCleanup, onError, onMount, requestCallback, runWithOwner, sharedConfig, splitProps, startTransition, untrack, useContext, useTransition };