deno.land / x / solid@v1.5.6 / src / reactive / signal.ts
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709// Inspired by S.js by Adam Haile, https://github.com/adamhaile/S
import { requestCallback, Task } from "./scheduler.js";import { setHydrateContext, sharedConfig } from "../render/hydration.js";import type { JSX } from "../jsx.js";import type { FlowComponent, FlowProps } from "../render/index.js";
export const equalFn = <T>(a: T, b: T) => a === b;export const $PROXY = Symbol("solid-proxy");export const $TRACK = Symbol("solid-track");export const $DEVCOMP = Symbol("solid-dev-component");const signalOptions = { equals: equalFn };let ERROR: symbol | null = null;let runEffects = runQueue;const STALE = 1;const PENDING = 2;const UNOWNED: Owner = { owned: null, cleanups: null, context: null, owner: null};const NO_INIT = {};export var Owner: Owner | null = null;export let Transition: TransitionState | null = null;let Scheduler: ((fn: () => void) => any) | null = null;let ExternalSourceFactory: ExternalSourceFactory | null = null;let Listener: Computation<any> | null = null;let Updates: Computation<any>[] | null = null;let Effects: Computation<any>[] | null = null;let ExecCount = 0;let rootCount = 0;
// keep immediately evaluated module code, below its indirect declared let dependencies like Listenerconst [transPending, setTransPending] = /*@__PURE__*/ createSignal(false);
declare global { var _$afterUpdate: () => void; var _$afterCreateRoot: (root: Owner) => void;}
export interface SignalState<T> { value?: T; observers: Computation<any>[] | null; observerSlots: number[] | null; tValue?: T; comparator?: (prev: T, next: T) => boolean; name?: string;}
export interface Owner { owned: Computation<any>[] | null; cleanups: (() => void)[] | null; owner: Owner | null; context: any | null; sourceMap?: Record<string, { value: unknown }>; name?: string; componentName?: string;}
export interface Computation<Init, Next extends Init = Init> extends Owner { fn: EffectFunction<Init, Next>; state: number; tState?: number; sources: SignalState<Next>[] | null; sourceSlots: number[] | null; value?: Init; updatedAt: number | null; pure: boolean; user?: boolean; suspense?: SuspenseContextType;}
export interface TransitionState { sources: Set<SignalState<any>>; effects: Computation<any>[]; promises: Set<Promise<any>>; disposed: Set<Computation<any>>; queue: Set<Computation<any>>; scheduler?: (fn: () => void) => unknown; running: boolean; done?: Promise<void>; resolve?: () => void;}
type ExternalSourceFactory = <Prev, Next extends Prev = Prev>( fn: EffectFunction<Prev, Next>, trigger: () => void) => ExternalSource;
export interface ExternalSource { track: EffectFunction<any, any>; dispose: () => void;}
export type RootFunction<T> = (dispose: () => void) => T;
/** * Creates a new non-tracked reactive context that doesn't auto-dispose * * @param fn a function in which the reactive state is scoped * @param detachedOwner optional reactive context to bind the root to * @returns the output of `fn`. * * @description https://www.solidjs.com/docs/latest/api#createroot */export function createRoot<T>(fn: RootFunction<T>, detachedOwner?: Owner): T { const listener = Listener, owner = Owner, unowned = fn.length === 0, root: Owner = unowned && !"_SOLID_DEV_" ? UNOWNED : { owned: null, cleanups: null, context: null, owner: detachedOwner || owner }, updateFn = unowned ? "_SOLID_DEV_" ? () => fn(() => { throw new Error("Dispose method must be an explicit argument to createRoot function"); }) : fn : () => fn(() => untrack(() => cleanNode(root)));
if ("_SOLID_DEV_") { if (owner) root.name = `${owner.name}-r${rootCount++}`; globalThis._$afterCreateRoot && globalThis._$afterCreateRoot(root); }
Owner = root; Listener = null;
try { return runUpdates(updateFn as () => T, true)!; } finally { Listener = listener; Owner = owner; }}
export type Accessor<T> = () => T;
export type Setter<T> = (undefined extends T ? () => undefined : {}) & (<U extends T>(value: (prev: T) => U) => U) & (<U extends T>(value: Exclude<U, Function>) => U) & (<U extends T>(value: Exclude<U, Function> | ((prev: T) => U)) => U);
export type Signal<T> = [get: Accessor<T>, set: Setter<T>];
export interface SignalOptions<T> extends MemoOptions<T> { internal?: boolean;}
/** * Creates a simple reactive state with a getter and setter * ```typescript * const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( * value: T, * options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } * ) * ``` * @param value initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error * @param options optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity * * @returns ```typescript * [state: Accessor<T>, setState: Setter<T>] * ``` * * the Accessor is merely a function that returns the current value and registers each call to the reactive root * * the Setter is a function that allows directly setting or mutating the value: * ```typescript * const [count, setCount] = createSignal(0); * setCount(count => count + 1); * ``` * * @description https://www.solidjs.com/docs/latest/api#createsignal */export function createSignal<T>(): Signal<T | undefined>;export function createSignal<T>(value: T, options?: SignalOptions<T>): Signal<T>;export function createSignal<T>(value?: T, options?: SignalOptions<T>): Signal<T | undefined> { options = options ? Object.assign({}, signalOptions, options) : signalOptions;
const s: SignalState<T> = { value, observers: null, observerSlots: null, comparator: options.equals || undefined };
if ("_SOLID_DEV_" && !options.internal) s.name = registerGraph(options.name || hashValue(value), s as { value: unknown });
const setter: Setter<T | undefined> = (value?: unknown) => { 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];}
export interface BaseOptions { name?: string;}
// Magic type that when used at sites where generic types are inferred from, will prevent those sites from being involved in the inference.// https://github.com/microsoft/TypeScript/issues/14829// TypeScript Discord conversation: https://discord.com/channels/508357248330760243/508357248330760249/911266491024949328export type NoInfer<T extends any> = [T][T extends any ? 0 : never];
export interface EffectOptions extends BaseOptions {}
// Also similar to OnEffectFunctionexport type EffectFunction<Prev, Next extends Prev = Prev> = (v: Prev) => Next;
/** * Creates a reactive computation that runs immediately before render, mainly used to write to other reactive primitives * ```typescript * export function createComputed<Next, Init = Next>( * fn: (v: Init | Next) => Next, * value?: Init, * options?: { name?: string } * ): void; * ``` * @param fn a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument * @param options allows to set a name in dev mode for debugging purposes * * @description https://www.solidjs.com/docs/latest/api#createcomputed */export function createComputed<Next>(fn: EffectFunction<undefined | NoInfer<Next>, Next>): void;export function createComputed<Next, Init = Next>( fn: EffectFunction<Init | Next, Next>, value: Init, options?: EffectOptions): void;export function createComputed<Next, Init>( fn: EffectFunction<Init | Next, Next>, value?: Init, options?: EffectOptions): void { const c = createComputation(fn, value!, true, STALE, "_SOLID_DEV_" ? options : undefined); if (Scheduler && Transition && Transition.running) Updates!.push(c); else updateComputation(c);}
/** * Creates a reactive computation that runs during the render phase as DOM elements are created and updated but not necessarily connected * ```typescript * export function createRenderEffect<T>( * fn: (v: T) => T, * value?: T, * options?: { name?: string } * ): void; * ``` * @param fn a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument * @param options allows to set a name in dev mode for debugging purposes * * @description https://www.solidjs.com/docs/latest/api#createrendereffect */export function createRenderEffect<Next>(fn: EffectFunction<undefined | NoInfer<Next>, Next>): void;export function createRenderEffect<Next, Init = Next>( fn: EffectFunction<Init | Next, Next>, value: Init, options?: EffectOptions): void;export function createRenderEffect<Next, Init>( fn: EffectFunction<Init | Next, Next>, value?: Init, options?: EffectOptions): void { const c = createComputation(fn, value!, false, STALE, "_SOLID_DEV_" ? options : undefined); if (Scheduler && Transition && Transition.running) Updates!.push(c); else updateComputation(c);}
/** * Creates a reactive computation that runs after the render phase * ```typescript * export function createEffect<T>( * fn: (v: T) => T, * value?: T, * options?: { name?: string } * ): void; * ``` * @param fn a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument * @param options allows to set a name in dev mode for debugging purposes * * @description https://www.solidjs.com/docs/latest/api#createeffect */export function createEffect<Next>(fn: EffectFunction<undefined | NoInfer<Next>, Next>): void;export function createEffect<Next, Init = Next>( fn: EffectFunction<Init | Next, Next>, value: Init, options?: EffectOptions): void;export function createEffect<Next, Init>( fn: EffectFunction<Init | Next, Next>, value?: Init, options?: EffectOptions): void { runEffects = runUserEffects; const c = createComputation(fn, value!, false, STALE, "_SOLID_DEV_" ? options : undefined), s = SuspenseContext && lookup(Owner, SuspenseContext.id); if (s) c.suspense = s; c.user = true; Effects ? Effects.push(c) : updateComputation(c);}
/** * Creates a reactive computation that runs after the render phase with flexible tracking * ```typescript * export function createReaction( * onInvalidate: () => void, * options?: { name?: string } * ): (fn: () => void) => void; * ``` * @param invalidated a function that is called when tracked function is invalidated. * @param options allows to set a name in dev mode for debugging purposes * * @description https://www.solidjs.com/docs/latest/api#createreaction */export function createReaction(onInvalidate: () => void, options?: EffectOptions) { let fn: (() => void) | undefined; const c = createComputation( () => { fn ? fn() : untrack(onInvalidate); fn = undefined; }, undefined, false, 0, "_SOLID_DEV_" ? options : undefined ), s = SuspenseContext && lookup(Owner, SuspenseContext.id); if (s) c.suspense = s; c.user = true; return (tracking: () => void) => { fn = tracking; updateComputation(c); };}
interface Memo<Prev, Next = Prev> extends SignalState<Next>, Computation<Next> { tOwned?: Computation<Prev | Next, Next>[];}
export interface MemoOptions<T> extends EffectOptions { equals?: false | ((prev: T, next: T) => boolean);}
/** * Creates a readonly derived reactive memoized signal * ```typescript * export function createMemo<T>( * fn: (v: T) => T, * value?: T, * options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } * ): () => T; * ``` * @param fn a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument * @param options allows to set a name in dev mode for debugging purposes and use a custom comparison function in equals * * @description https://www.solidjs.com/docs/latest/api#creatememo */// The extra Prev generic parameter separates inference of the effect input// parameter type from inference of the effect return type, so that the effect// return type is always used as the memo Accessor's return type.export function createMemo<Next extends Prev, Prev = Next>( fn: EffectFunction<undefined | NoInfer<Prev>, Next>): Accessor<Next>;export function createMemo<Next extends Prev, Init = Next, Prev = Next>( fn: EffectFunction<Init | Prev, Next>, value: Init, options?: MemoOptions<Next>): Accessor<Next>;export function createMemo<Next extends Prev, Init, Prev>( fn: EffectFunction<Init | Prev, Next>, value?: Init, options?: MemoOptions<Next>): Accessor<Next> { options = options ? Object.assign({}, signalOptions, options) : signalOptions;
const c: Partial<Memo<Init, Next>> = createComputation( fn, value!, true, 0, "_SOLID_DEV_" ? options : undefined ) as Partial<Memo<Init, Next>>;
c.observers = null; c.observerSlots = null; c.comparator = options.equals || undefined; if (Scheduler && Transition && Transition.running) { c.tState = STALE; Updates!.push(c as Memo<Init, Next>); } else updateComputation(c as Memo<Init, Next>); return readSignal.bind(c as Memo<Init, Next>);}
interface Unresolved { state: "unresolved"; loading: false; error: undefined; latest: undefined; (): undefined;}
interface Pending { state: "pending"; loading: true; error: undefined; latest: undefined; (): undefined;}
interface Ready<T> { state: "ready"; loading: false; error: undefined; latest: T; (): T;}
interface Refreshing<T> { state: "refreshing"; loading: true; error: undefined; latest: T; (): T;}
interface Errored { state: "errored"; loading: false; error: any; latest: never; (): never;}
export type Resource<T> = Unresolved | Pending | Ready<T> | Refreshing<T> | Errored;
export type InitializedResource<T> = Ready<T> | Refreshing<T> | Errored;
export type ResourceActions<T, R = unknown> = { mutate: Setter<T>; refetch: (info?: R) => T | Promise<T> | undefined | null;};
export type ResourceSource<S> = S | false | null | undefined | (() => S | false | null | undefined);
export type ResourceFetcher<S, T, R = unknown> = ( k: S, info: ResourceFetcherInfo<T, R>) => T | Promise<T>;
export type ResourceFetcherInfo<T, R = unknown> = { value: T | undefined; refetching: R | boolean;};
export type ResourceOptions<T, S = unknown> = { initialValue?: T; name?: string; deferStream?: boolean; ssrLoadFrom?: "initial" | "server"; storage?: (init: T | undefined) => [Accessor<T | undefined>, Setter<T | undefined>]; onHydrated?: (k: S | undefined, info: { value: T | undefined }) => void;};
export type InitializedResourceOptions<T, S = unknown> = ResourceOptions<T, S> & { initialValue: T;};
export type ResourceReturn<T, R = unknown> = [Resource<T>, ResourceActions<T | undefined, R>];
export type InitializedResourceReturn<T, R = unknown> = [ InitializedResource<T>, ResourceActions<T, R>];
/** * Creates a resource that wraps a repeated promise in a reactive pattern: * ```typescript * // Without source * const [resource, { mutate, refetch }] = createResource(fetcher, options); * // With source * const [resource, { mutate, refetch }] = createResource(source, fetcher, options); * ``` * @param source - reactive data function which has its non-nullish and non-false values passed to the fetcher, optional * @param fetcher - function that receives the source (true if source not provided), the last or initial value, and whether the resource is being refetched, and returns a value or a Promise: * ```typescript * const fetcher: ResourceFetcher<S, T, R> = ( * sourceOutput: S, * info: { value: T | undefined, refetching: R | boolean } * ) => T | Promise<T>; * ``` * @param options - an optional object with the initialValue and the name (for debugging purposes); see {@link ResourceOptions} * * @returns ```typescript * [Resource<T>, { mutate: Setter<T>, refetch: () => void }] * ``` * * * Setting an `initialValue` in the options will mean that both the prev() accessor and the resource should never return undefined (if that is wanted, you need to extend the type with undefined) * * `mutate` allows to manually overwrite the resource without calling the fetcher * * `refetch` will re-run the fetcher without changing the source, and if called with a value, that value will be passed to the fetcher via the `refetching` property on the fetcher's second parameter * * @description https://www.solidjs.com/docs/latest/api#createresource */export function createResource<T, R = unknown>( fetcher: ResourceFetcher<true, T, R>, options: InitializedResourceOptions<NoInfer<T>, true>): InitializedResourceReturn<T, R>;export function createResource<T, R = unknown>( fetcher: ResourceFetcher<true, T, R>, options?: ResourceOptions<NoInfer<T>, true>): ResourceReturn<T, R>;export function createResource<T, S, R = unknown>( source: ResourceSource<S>, fetcher: ResourceFetcher<S, T, R>, options: InitializedResourceOptions<NoInfer<T>, S>): InitializedResourceReturn<T, R>;export function createResource<T, S, R = unknown>( source: ResourceSource<S>, fetcher: ResourceFetcher<S, T, R>, options?: ResourceOptions<NoInfer<T>, S>): ResourceReturn<T, R>;export function createResource<T, S, R>( pSource: ResourceSource<S> | ResourceFetcher<S, T, R>, pFetcher?: ResourceFetcher<S, T, R> | ResourceOptions<T, S>, pOptions?: ResourceOptions<T, S> | undefined): ResourceReturn<T, R> { let source: ResourceSource<S>; let fetcher: ResourceFetcher<S, T, R>; let options: ResourceOptions<T, S>; if ((arguments.length === 2 && typeof pFetcher === "object") || arguments.length === 1) { source = true as ResourceSource<S>; fetcher = pSource as ResourceFetcher<S, T, R>; options = (pFetcher || {}) as ResourceOptions<T, S>; } else { source = pSource as ResourceSource<S>; fetcher = pFetcher as ResourceFetcher<S, T, R>; options = pOptions || ({} as ResourceOptions<T, S>); }
let pr: Promise<T> | null = null, initP: Promise<T> | T | typeof NO_INIT = NO_INIT, id: string | null = null, loadedUnderTransition: boolean | null = false, scheduled = false, resolved = "initialValue" in options, dynamic = typeof source === "function" && createMemo(source as () => S | false | null | undefined);
const contexts = new Set<SuspenseContextType>(), [value, setValue] = (options.storage || createSignal)(options.initialValue) as Signal< T | undefined >, [error, setError] = createSignal<unknown>(undefined), [track, trigger] = createSignal(undefined, { equals: false }), [state, setState] = createSignal<"unresolved" | "pending" | "ready" | "refreshing" | "errored">( resolved ? "ready" : "unresolved" );
if (sharedConfig.context) { id = `${sharedConfig.context.id}${sharedConfig.context.count++}`; let v; if (options.ssrLoadFrom === "initial") initP = options.initialValue as T; else if (sharedConfig.load && (v = sharedConfig.load(id))) initP = v[0]; } function loadEnd(p: Promise<T> | null, v: T | undefined, error?: any, key?: S) { 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; if (!Transition!.promises.size) { Effects!.push.apply(Effects, Transition!.effects); Transition!.effects = []; } completeLoad(v, error); }, false); } else completeLoad(v, error); } return v; } function completeLoad(v: T | undefined, err: any) { runUpdates(() => { if (!err) setValue(() => v); setError(err); setState(err ? "errored" : "ready"); 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) Transition.promises.add(pr); else if (!contexts.has(c)) { c.increment(); contexts.add(c); } } }); } return v; } function load(refetching: R | boolean = true) { if (refetching !== false && scheduled) return; scheduled = false; const lookup = dynamic ? dynamic() : (source as S); 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 as T | Promise<T>) : untrack(() => fetcher(lookup, { value: value(), refetching }) ); if (typeof p !== "object" || !(p && "then" in p)) { loadEnd(pr, p); 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)) ) as Promise<T>; } 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 as Resource<T>, { refetch: load, mutate: setValue }];}
export interface DeferredOptions<T> { equals?: false | ((prev: T, next: T) => boolean); name?: string; timeoutMs?: number;}
/** * Creates a reactive computation that only runs and notifies the reactive context when the browser is idle * ```typescript * export function createDeferred<T>( * fn: (v: T) => T, * options?: { timeoutMs?: number, name?: string, equals?: false | ((prev: T, next: T) => boolean) } * ): () => T); * ``` * @param fn a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation * @param options allows to set the timeout in milliseconds, use a custom comparison function and set a name in dev mode for debugging purposes * * @description https://www.solidjs.com/docs/latest/api#createdeferred */export function createDeferred<T>(source: Accessor<T>, options?: DeferredOptions<T>) { let t: Task, timeout = options ? options.timeoutMs : undefined; const node = createComputation( () => { if (!t || !t.fn) t = requestCallback( () => setDeferred(() => node.value as T), timeout !== undefined ? { timeout } : undefined ); return source(); }, undefined, true ); const [deferred, setDeferred] = createSignal(node.value as T, options); updateComputation(node); setDeferred(() => node.value as T); return deferred;}
export type EqualityCheckerFunction<T, U> = (a: U, b: T) => boolean;
/** * Creates a conditional signal that only notifies subscribers when entering or exiting their key matching the value * ```typescript * export function createSelector<T, U>( * source: () => T * fn: (a: U, b: T) => boolean, * options?: { name?: string } * ): (k: U) => boolean; * ``` * @param source * @param fn a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation * @param options allows to set a name in dev mode for debugging purposes, optional * * ```typescript * const isSelected = createSelector(selectedId); * <For each={list()}> * {(item) => <li classList={{ active: isSelected(item.id) }}>{item.name}</li>} * </For> * ``` * * This makes the operation O(2) instead of O(n). * * @description https://www.solidjs.com/docs/latest/api#createselector */export function createSelector<T, U>( source: Accessor<T>, fn: EqualityCheckerFunction<T, U> = equalFn as TODO, options?: BaseOptions): (key: U) => boolean { const subs = new Map<U, Set<Computation<any>>>(); const node = createComputation( (p: T | undefined) => { 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, "_SOLID_DEV_" ? options : undefined ) as Memo<any>; updateComputation(node); return (key: U) => { const listener = Listener; if (listener) { let l: Set<Computation<any>> | undefined; 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! ); };}
/** * Holds changes inside the block before the reactive context is updated * @param fn wraps the reactive updates that should be batched * @returns the return value from `fn` * * @description https://www.solidjs.com/docs/latest/api#batch */export function batch<T>(fn: Accessor<T>): T { return runUpdates(fn, false) as T;}
/** * Ignores tracking context inside its scope * @param fn the scope that is out of the tracking context * @returns the return value of `fn` * * @description https://www.solidjs.com/docs/latest/api#untrack */export function untrack<T>(fn: Accessor<T>): T { let result: T, listener = Listener;
Listener = null; result = fn(); Listener = listener;
return result;}
/** @deprecated */export type ReturnTypes<T> = T extends readonly Accessor<unknown>[] ? { [K in keyof T]: T[K] extends Accessor<infer I> ? I : never } : T extends Accessor<infer I> ? I : never;
// transforms a tuple to a tuple of accessors in a way that allows generics to be inferredexport type AccessorArray<T> = [...Extract<{ [K in keyof T]: Accessor<T[K]> }, readonly unknown[]>];
// Also similar to EffectFunctionexport type OnEffectFunction<S, Prev, Next extends Prev = Prev> = ( input: S, prevInput: S | undefined, prev: Prev) => Next;
export interface OnOptions { defer?: boolean;}
/** * on - make dependencies of a computation explicit * ```typescript * export function on<S, U>( * deps: Accessor<S> | AccessorArray<S>, * fn: (input: S, prevInput: S | undefined, prevValue: U | undefined) => U, * options?: { defer?: boolean } = {} * ): (prevValue: U | undefined) => U; * ``` * @param deps list of reactive dependencies or a single reactive dependency * @param fn computation on input; the current previous content(s) of input and the previous value are given as arguments and it returns a new value * @param options optional, allows deferred computation until at the end of the next change * @returns an effect function that is passed into createEffect. For example: * * ```typescript * createEffect(on(a, (v) => console.log(v, b()))); * * // is equivalent to: * createEffect(() => { * const v = a(); * untrack(() => console.log(v, b())); * }); * ``` * * @description https://www.solidjs.com/docs/latest/api#on */export function on<S, Next extends Prev, Prev = Next>( deps: AccessorArray<S> | Accessor<S>, fn: OnEffectFunction<S, undefined | NoInfer<Prev>, Next>, options?: OnOptions & { defer?: false }): EffectFunction<undefined | NoInfer<Next>, NoInfer<Next>>;export function on<S, Next extends Prev, Prev = Next>( deps: AccessorArray<S> | Accessor<S>, fn: OnEffectFunction<S, undefined | NoInfer<Prev>, Next>, options: OnOptions & { defer: true }): EffectFunction<undefined | NoInfer<Next>>;export function on<S, Next extends Prev, Prev = Next>( deps: AccessorArray<S> | Accessor<S>, fn: OnEffectFunction<S, undefined | NoInfer<Prev>, Next>, options?: OnOptions): EffectFunction<undefined | NoInfer<Next>> { const isArray = Array.isArray(deps); let prevInput: S; let defer = options && options.defer; return prevValue => { let input: S; if (isArray) { input = Array(deps.length) as unknown as S; for (let i = 0; i < deps.length; i++) (input as unknown as TODO[])[i] = deps[i](); } else input = deps(); if (defer) { defer = false; return undefined; } const result = untrack(() => fn(input, prevInput, prevValue)); prevInput = input; return result; };}
/** * onMount - run an effect only after initial render on mount * @param fn an effect that should run only once on mount * * @description https://www.solidjs.com/docs/latest/api#onmount */export function onMount(fn: () => void) { createEffect(() => untrack(fn));}
/** * onCleanup - run an effect once before the reactive scope is disposed * @param fn an effect that should run only once on cleanup * * @description https://www.solidjs.com/docs/latest/api#oncleanup */export function onCleanup(fn: () => void) { if (Owner === null) "_SOLID_DEV_" && 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;}
/** * onError - run an effect whenever an error is thrown within the context of the child scopes * @param fn an error handler that receives the error * * * If the error is thrown again inside the error handler, it will trigger the next available parent handler * * @description https://www.solidjs.com/docs/latest/api#onerror */export function onError(fn: (err: any) => void): void { ERROR || (ERROR = Symbol("error")); if (Owner === null) "_SOLID_DEV_" && 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);}
export function getListener() { return Listener;}
export function getOwner() { return Owner;}
export function runWithOwner<T>(o: Owner, fn: () => T): T { const prev = Owner; Owner = o; try { return runUpdates(fn, true)!; } finally { Owner = prev; }}
// Transitionsexport function enableScheduling(scheduler = requestCallback) { Scheduler = scheduler;}
/** * ```typescript * export function startTransition(fn: () => void) => Promise<void> * * @description https://www.solidjs.com/docs/latest/api#usetransition */export function startTransition(fn: () => unknown): Promise<void> { if (Transition && Transition.running) { fn(); return Transition.done!; } const l = Listener; const o = Owner; return Promise.resolve().then(() => { Listener = l; Owner = o; let t: TransitionState | undefined; 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; });}
export type Transition = [Accessor<boolean>, (fn: () => void) => Promise<void>];
/** * ```typescript * export function useTransition(): [ * () => boolean, * (fn: () => void, cb?: () => void) => void * ]; * @returns a tuple; first value is an accessor if the transition is pending and a callback to start the transition * * @description https://www.solidjs.com/docs/latest/api#usetransition */export function useTransition(): Transition { return [transPending, startTransition];}
export function resumeEffects(e: Computation<any>[]) { Effects!.push.apply(Effects, e); e.length = 0;}
export interface DevComponent<T> extends Memo<JSX.Element> { props: T; componentName: string;}
// Devexport function devComponent<T>(Comp: (props: T) => JSX.Element, props: T) { const c = createComputation( () => untrack(() => { Object.assign(Comp, { [$DEVCOMP]: true }); return Comp(props); }), undefined, true ) as DevComponent<T>; c.props = props; c.observers = null; c.observerSlots = null; c.state = 0; c.componentName = Comp.name; updateComputation(c); return c.tValue !== undefined ? c.tValue : c.value;}
export function hashValue(v: any): string { 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]; // skip getters if (!value.get) memo[key] = value; return memo; }, {} as any); v = Object.create({}, newDesc); } if (typeof v === "bigint") { return `${v.toString()}n`; } return v; }) || "" ) ) }`;}
export function registerGraph(name: string, value: { value: unknown }): string { let tryName = name; if (Owner) { let i = 0; Owner.sourceMap || (Owner.sourceMap = {}); while (Owner.sourceMap[tryName]) tryName = `${name}-${++i}`; Owner.sourceMap[tryName] = value; } return tryName;}interface GraphRecord { [k: string]: GraphRecord | unknown;}export function serializeGraph(owner?: Owner | null): GraphRecord { owner || (owner = Owner); if (!"_SOLID_DEV_" || !owner) return {}; return { ...serializeValues(owner.sourceMap), ...(owner.owned ? serializeChildren(owner) : {}) };}
export type ContextProviderComponent<T> = FlowComponent<{ value: T }>;
// Context APIexport interface Context<T> { id: symbol; Provider: ContextProviderComponent<T>; defaultValue: T;}
/** * Creates a Context to handle a state scoped for the children of a component * ```typescript * interface Context<T> { * id: symbol; * Provider: FlowComponent<{ value: T }>; * defaultValue: T; * } * export function createContext<T>(defaultValue?: T): Context<T | undefined>; * ``` * @param defaultValue optional default to inject into context * @returns The context that contains the Provider Component and that can be used with `useContext` * * @description https://www.solidjs.com/docs/latest/api#createcontext */export function createContext<T>(): Context<T | undefined>;export function createContext<T>(defaultValue: T): Context<T>;export function createContext<T>(defaultValue?: T): Context<T | undefined> { const id = Symbol("context"); return { id, Provider: createProvider(id), defaultValue };}
/** * use a context to receive a scoped state from a parent's Context.Provider * * @param context Context object made by `createContext` * @returns the current or `defaultValue`, if present * * @description https://www.solidjs.com/docs/latest/api#usecontext */export function useContext<T>(context: Context<T>): T { let ctx; return (ctx = lookup(Owner, context.id)) !== undefined ? ctx : context.defaultValue;}
export type ResolvedJSXElement = Exclude<JSX.Element, JSX.ArrayElement | JSX.FunctionElement>;export type ResolvedChildren = ResolvedJSXElement | ResolvedJSXElement[];export type ChildrenReturn = Accessor<ResolvedChildren> & { toArray: () => ResolvedJSXElement[] };
/** * Resolves child elements to help interact with children * * @param fn an accessor for the children * @returns a accessor of the same children, but resolved * * @description https://www.solidjs.com/docs/latest/api#children */export function children(fn: Accessor<JSX.Element>): ChildrenReturn { const children = createMemo(fn); const memo = createMemo(() => resolveChildren(children())); (memo as ChildrenReturn).toArray = () => { const c = memo(); return Array.isArray(c) ? c : c != null ? [c] : []; }; return memo as ChildrenReturn;}
// Resource APIexport type SuspenseContextType = { increment?: () => void; decrement?: () => void; inFallback?: () => boolean; effects?: Computation<any>[]; resolved?: boolean;};
type SuspenseContext = Context<SuspenseContextType> & { active?(): boolean; increment?(): void; decrement?(): void;};
let SuspenseContext: SuspenseContext;
export function getSuspenseContext() { return SuspenseContext || (SuspenseContext = createContext<SuspenseContextType>({}));}
// Interopexport function enableExternalSource(factory: ExternalSourceFactory) { 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; }}
// Internalexport function readSignal(this: SignalState<any> | Memo<any>) { const runningTransition = Transition && Transition.running; if ( (this as Memo<any>).sources && ((!runningTransition && (this as Memo<any>).state) || (runningTransition && (this as Memo<any>).tState)) ) { if ( (!runningTransition && (this as Memo<any>).state === STALE) || (runningTransition && (this as Memo<any>).tState === STALE) ) updateComputation(this as Memo<any>); else { const updates = Updates; Updates = null; runUpdates(() => lookUpstream(this as Memo<any>), 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;}
export function writeSignal(node: SignalState<any> | Memo<any>, value: any, isComp?: boolean) { 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 as Memo<any>).observers) markDownstream(o as Memo<any>); } 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: Computation<any>) { 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 as Memo<any>) ? (node as Memo<any>).tValue : node.value, time );
if (Transition && !Transition.running && Transition.sources.has(node as Memo<any>)) { queueMicrotask(() => { runUpdates(() => { Transition && (Transition.running = true); runComputation(node, (node as Memo<any>).tValue, time); }, false); }); } Listener = listener; Owner = owner;}
function runComputation(node: Computation<any>, value: any, time: number) { let nextValue; try { nextValue = node.fn(value); } catch (err) { if (node.pure) Transition && Transition.running ? (node.tState = STALE) : (node.state = STALE); handleError(err); } if (!node.updatedAt || node.updatedAt <= time) { if (node.updatedAt != null && "observers" in (node as Memo<any>)) { writeSignal(node as Memo<any>, nextValue, true); } else if (Transition && Transition.running && node.pure) { Transition.sources.add(node as Memo<any>); (node as Memo<any>).tValue = nextValue; } else node.value = nextValue; node.updatedAt = time; }}
function createComputation<Next, Init = unknown>( fn: EffectFunction<Init | Next, Next>, init: Init, pure: boolean, state: number = STALE, options?: EffectOptions): Computation<Init | Next, Next> { const c: Computation<Init | Next, Next> = { 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) "_SOLID_DEV_" && console.warn( "computations created outside a `createRoot` or `render` will never be disposed" ); else if (Owner !== UNOWNED) { if (Transition && Transition.running && (Owner as Memo<Init, Next>).pure) { if (!(Owner as Memo<Init, Next>).tOwned) (Owner as Memo<Init, Next>).tOwned = [c]; else (Owner as Memo<Init, Next>).tOwned!.push(c); } else { if (!Owner.owned) Owner.owned = [c]; else Owner.owned.push(c); } if ("_SOLID_DEV_") c.name = (options && options.name) || `${(Owner as Computation<any>).name || "c"}-${ (Owner.owned || (Owner as Memo<Init, Next>).tOwned!).length }`; }
if (ExternalSourceFactory) { const [track, trigger] = createSignal<void>(undefined, { equals: false }); const ordinary = ExternalSourceFactory(c.fn, trigger); onCleanup(() => ordinary.dispose()); const triggerInTransition: () => void = () => 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: Computation<any>) { 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 as Computation<any>) && (!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 as Computation<any>) && 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<T>(fn: () => T, init: boolean) { 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: boolean) { if (Updates) { if (Scheduler && Transition && Transition.running) scheduleQueue(Updates); else runQueue(Updates); Updates = null; } if (wait) return; let res; 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; } // finish transition const sources = Transition.sources; const disposed = Transition.disposed; 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 as Memo<any>).owned) { for (let i = 0, len = (v as Memo<any>).owned!.length; i < len; i++) cleanNode((v as Memo<any>).owned![i]); } if ((v as Memo<any>).tOwned) (v as Memo<any>).owned = (v as Memo<any>).tOwned!; delete v.tValue; delete (v as Memo<any>).tOwned; (v as Memo<any>).tState = 0; } setTransPending(false); }, false); } const e = Effects!; Effects = null; if (e!.length) runUpdates(() => runEffects(e), false); else if ("_SOLID_DEV_") globalThis._$afterUpdate && globalThis._$afterUpdate(); if (res) res();}
function runQueue(queue: Computation<any>[]) { for (let i = 0; i < queue.length; i++) runTop(queue[i]);}
function scheduleQueue(queue: Computation<any>[]) { 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: Computation<any>[]) { 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: Computation<any>, ignore?: Computation<any>) { 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] as Memo<any>; 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: Memo<any>) { 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 as Memo<any>).observers && markDownstream(o as Memo<any>); } }}
function cleanNode(node: Owner) { let i; if ((node as Computation<any>).sources) { while ((node as Computation<any>).sources!.length) { const source = (node as Computation<any>).sources!.pop()!, index = (node as Computation<any>).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 as Memo<any>).pure) { if ((node as Memo<any>).tOwned) { for (i = 0; i < (node as Memo<any>).tOwned!.length; i++) cleanNode((node as Memo<any>).tOwned![i]); delete (node as Memo<any>).tOwned; } reset(node as Computation<any>, 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 as Computation<any>).tState = 0; else (node as Computation<any>).state = 0; node.context = null; "_SOLID_DEV_" && delete node.sourceMap;}
function reset(node: Computation<any>, top?: boolean) { 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: any) { if (err instanceof Error || typeof err === "string") return err; return new Error("Unknown error");}
function handleError(err: any) { err = castError(err); const fns = ERROR && lookup(Owner, ERROR); if (!fns) throw err; for (const f of fns) f(err);}
function lookup(owner: Owner | null, key: symbol | string): any { return owner ? owner.context && owner.context[key] !== undefined ? owner.context[key] : lookup(owner.owner, key) : undefined;}
function resolveChildren(children: JSX.Element): ResolvedChildren { if (typeof children === "function" && !children.length) return resolveChildren(children()); if (Array.isArray(children)) { const results: any[] = []; 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 as ResolvedChildren;}
function createProvider(id: symbol) { return function provider(props: FlowProps<{ value: unknown }>) { let res; createRenderEffect( () => (res = untrack(() => { Owner!.context = { [id]: props.value }; return children(() => props.children); })) ); return res; };}
function hash(s: string) { 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: Record<string, { value: unknown }> = {}) { const k = Object.keys(sources); const result: Record<string, unknown> = {}; for (let i = 0; i < k.length; i++) { const key = k[i]; result[key] = sources[key].value; } return result;}
function serializeChildren(root: Owner): GraphRecord { const result: GraphRecord = {}; 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;}
type TODO = any;
Version Info