+429
-41
@@ -42,4 +42,11 @@ 'use strict'; | ||
| }); | ||
| return Comp(props); | ||
| signals.setStrictRead(`<${Comp.name || "Anonymous"}>`); | ||
| try { | ||
| return Comp(props); | ||
| } finally { | ||
| signals.setStrictRead(false); | ||
| } | ||
| }); | ||
| }, { | ||
| transparent: true | ||
| }); | ||
@@ -64,4 +71,40 @@ } | ||
| }; | ||
| let _hydrationEndCallbacks = null; | ||
| let _pendingBoundaries = 0; | ||
| let _hydrationDone = false; | ||
| let _snapshotRootOwner = null; | ||
| function markTopLevelSnapshotScope() { | ||
| if (_snapshotRootOwner) return; | ||
| let owner = signals.getOwner(); | ||
| if (!owner) return; | ||
| while (owner._parent) owner = owner._parent; | ||
| signals.markSnapshotScope(owner); | ||
| _snapshotRootOwner = owner; | ||
| } | ||
| function drainHydrationCallbacks() { | ||
| if (_hydrationDone) return; | ||
| _hydrationDone = true; | ||
| _doneValue = true; | ||
| signals.clearSnapshots(); | ||
| signals.setSnapshotCapture(false); | ||
| signals.flush(); | ||
| const cbs = _hydrationEndCallbacks; | ||
| _hydrationEndCallbacks = null; | ||
| if (cbs) for (const cb of cbs) cb(); | ||
| setTimeout(() => { | ||
| if (globalThis._$HY) globalThis._$HY.done = true; | ||
| }); | ||
| } | ||
| function checkHydrationComplete() { | ||
| if (_pendingBoundaries === 0) drainHydrationCallbacks(); | ||
| } | ||
| let _hydratingValue = false; | ||
| let _doneValue = false; | ||
| let _createMemo; | ||
| let _createSignal; | ||
| let _createErrorBoundary; | ||
| let _createOptimistic; | ||
| let _createProjection; | ||
| let _createStore; | ||
| let _createOptimisticStore; | ||
| class MockPromise { | ||
@@ -102,3 +145,7 @@ static all() { | ||
| Promise = MockPromise; | ||
| return fn(prev); | ||
| const result = fn(prev); | ||
| if (result && typeof result[Symbol.asyncIterator] === "function") { | ||
| result[Symbol.asyncIterator]().next(); | ||
| } | ||
| return result; | ||
| } finally { | ||
@@ -109,4 +156,96 @@ window.fetch = ogFetch; | ||
| } | ||
| function consumeFirstSync(ai) { | ||
| const iter = ai[Symbol.asyncIterator](); | ||
| const r = iter.next(); | ||
| const value = !(r instanceof Promise) && !r.done ? r.value : undefined; | ||
| return [value, iter]; | ||
| } | ||
| function applyPatches(target, patches) { | ||
| for (const patch of patches) { | ||
| const path = patch[0]; | ||
| let current = target; | ||
| for (let i = 0; i < path.length - 1; i++) current = current[path[i]]; | ||
| const key = path[path.length - 1]; | ||
| if (patch.length === 1) { | ||
| Array.isArray(current) ? current.splice(key, 1) : delete current[key]; | ||
| } else if (patch.length === 3) { | ||
| current.splice(key, 0, patch[1]); | ||
| } else { | ||
| current[key] = patch[1]; | ||
| } | ||
| } | ||
| } | ||
| function scheduleIteratorConsumption(iter, apply) { | ||
| const consume = () => { | ||
| while (true) { | ||
| const n = iter.next(); | ||
| if (n instanceof Promise) { | ||
| n.then(r => { | ||
| if (r.done) return; | ||
| apply(r.value); | ||
| consume(); | ||
| }); | ||
| return; | ||
| } | ||
| if (n.done) break; | ||
| apply(n.value); | ||
| } | ||
| }; | ||
| consume(); | ||
| } | ||
| function isAsyncIterable(v) { | ||
| return v != null && typeof v[Symbol.asyncIterator] === "function"; | ||
| } | ||
| function hydrateSignalFromAsyncIterable(coreFn, compute, value, options) { | ||
| const parent = signals.getOwner(); | ||
| const expectedId = signals.peekNextChildId(parent); | ||
| if (!sharedConfig.has(expectedId)) return null; | ||
| const initP = sharedConfig.load(expectedId); | ||
| if (!isAsyncIterable(initP)) return null; | ||
| const [firstValue, iter] = consumeFirstSync(initP); | ||
| const [get, set] = signals.createSignal(firstValue); | ||
| const result = coreFn(() => get(), firstValue, options); | ||
| scheduleIteratorConsumption(iter, v => { | ||
| set(() => v); | ||
| signals.flush(); | ||
| }); | ||
| return result; | ||
| } | ||
| function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) { | ||
| const parent = signals.getOwner(); | ||
| const expectedId = signals.peekNextChildId(parent); | ||
| if (!sharedConfig.has(expectedId)) return null; | ||
| const initP = sharedConfig.load(expectedId); | ||
| if (!isAsyncIterable(initP)) return null; | ||
| const [firstState, iter] = consumeFirstSync(initP); | ||
| const [store, setStore] = coreFn(() => {}, firstState ?? initialValue, options); | ||
| scheduleIteratorConsumption(iter, patches => { | ||
| setStore(d => { | ||
| applyPatches(d, patches); | ||
| }); | ||
| }); | ||
| return [store, setStore]; | ||
| } | ||
| function hydratedCreateMemo(compute, value, options) { | ||
| if (!sharedConfig.hydrating) return signals.createMemo(compute, value, options); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = options?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = signals.createSignal(false); | ||
| const memo = signals.createMemo(prev => { | ||
| if (!hydrated()) return prev ?? value; | ||
| return compute(prev); | ||
| }, value, options); | ||
| setHydrated(true); | ||
| return memo; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return signals.createMemo(prev => { | ||
| if (!sharedConfig.hydrating) return compute(prev); | ||
| subFetch(compute, prev); | ||
| return prev ?? value; | ||
| }, value, options); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(signals.createMemo, compute, value, options); | ||
| if (aiResult !== null) return aiResult; | ||
| return signals.createMemo(prev => { | ||
@@ -123,2 +262,22 @@ const o = signals.getOwner(); | ||
| if (typeof fn !== "function" || !sharedConfig.hydrating) return signals.createSignal(fn, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = signals.createSignal(false); | ||
| const sig = signals.createSignal(prev => { | ||
| if (!hydrated()) return prev ?? second; | ||
| return fn(prev); | ||
| }, second, third); | ||
| setHydrated(true); | ||
| return sig; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return signals.createSignal(prev => { | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| subFetch(fn, prev); | ||
| return prev ?? second; | ||
| }, second, third); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(signals.createSignal, fn, second, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return signals.createSignal(prev => { | ||
@@ -133,8 +292,201 @@ if (!sharedConfig.hydrating) return fn(prev); | ||
| } | ||
| function hydratedCreateErrorBoundary(fn, fallback) { | ||
| if (!sharedConfig.hydrating) return signals.createErrorBoundary(fn, fallback); | ||
| markTopLevelSnapshotScope(); | ||
| const parent = signals.getOwner(); | ||
| const expectedId = signals.peekNextChildId(parent); | ||
| if (sharedConfig.has(expectedId)) { | ||
| const err = sharedConfig.load(expectedId); | ||
| if (err !== undefined) { | ||
| let hydrated = true; | ||
| return signals.createErrorBoundary(() => { | ||
| if (hydrated) { | ||
| hydrated = false; | ||
| throw err; | ||
| } | ||
| return fn(); | ||
| }, fallback); | ||
| } | ||
| } | ||
| return signals.createErrorBoundary(fn, fallback); | ||
| } | ||
| function hydratedCreateOptimistic(fn, second, third) { | ||
| if (typeof fn !== "function" || !sharedConfig.hydrating) return signals.createOptimistic(fn, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = signals.createSignal(false); | ||
| const sig = signals.createOptimistic(prev => { | ||
| if (!hydrated()) return prev ?? second; | ||
| return fn(prev); | ||
| }, second, third); | ||
| setHydrated(true); | ||
| return sig; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return signals.createOptimistic(prev => { | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| subFetch(fn, prev); | ||
| return prev ?? second; | ||
| }, second, third); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(signals.createOptimistic, fn, second, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return signals.createOptimistic(prev => { | ||
| const o = signals.getOwner(); | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| let initP; | ||
| if (sharedConfig.has(o.id)) initP = sharedConfig.load(o.id); | ||
| const init = initP?.v ?? initP; | ||
| return init != null ? (subFetch(fn, prev), init) : fn(prev); | ||
| }, second, third); | ||
| } | ||
| function wrapStoreFn(fn, ssrSource) { | ||
| if (ssrSource === "initial") { | ||
| return draft => { | ||
| if (!sharedConfig.hydrating) return fn(draft); | ||
| subFetch(fn, draft); | ||
| return undefined; | ||
| }; | ||
| } | ||
| return draft => { | ||
| const o = signals.getOwner(); | ||
| if (!sharedConfig.hydrating) return fn(draft); | ||
| let initP; | ||
| if (sharedConfig.has(o.id)) initP = sharedConfig.load(o.id); | ||
| const init = initP?.v ?? initP; | ||
| return init != null ? (subFetch(fn, draft), init) : fn(draft); | ||
| }; | ||
| } | ||
| function hydratedCreateStore(first, second, third) { | ||
| if (typeof first !== "function" || !sharedConfig.hydrating) return signals.createStore(first, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return signals.createStore(second ?? {}, undefined, third); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(signals.createStore, second ?? {}, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return signals.createStore(wrapStoreFn(first, ssrSource), second, third); | ||
| } | ||
| function hydratedCreateOptimisticStore(first, second, third) { | ||
| if (typeof first !== "function" || !sharedConfig.hydrating) return signals.createOptimisticStore(first, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return signals.createOptimisticStore(second ?? {}, undefined, third); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(signals.createOptimisticStore, second ?? {}, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return signals.createOptimisticStore(wrapStoreFn(first, ssrSource), second, third); | ||
| } | ||
| function hydratedCreateProjection(fn, initialValue, options) { | ||
| if (!sharedConfig.hydrating) return signals.createProjection(fn, initialValue, options); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = options?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return signals.createProjection(draft => draft, initialValue, options); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(signals.createStore, initialValue, options); | ||
| if (aiResult !== null) return aiResult[0]; | ||
| return signals.createProjection(wrapStoreFn(fn, ssrSource), initialValue, options); | ||
| } | ||
| function enableHydration() { | ||
| _createMemo = hydratedCreateMemo; | ||
| _createSignal = hydratedCreateSignal; | ||
| _createErrorBoundary = hydratedCreateErrorBoundary; | ||
| _createOptimistic = hydratedCreateOptimistic; | ||
| _createProjection = hydratedCreateProjection; | ||
| _createStore = hydratedCreateStore; | ||
| _createOptimisticStore = hydratedCreateOptimisticStore; | ||
| _hydratingValue = sharedConfig.hydrating; | ||
| _doneValue = sharedConfig.done; | ||
| Object.defineProperty(sharedConfig, "hydrating", { | ||
| get() { | ||
| return _hydratingValue; | ||
| }, | ||
| set(v) { | ||
| const was = _hydratingValue; | ||
| _hydratingValue = v; | ||
| if (!was && v) { | ||
| _hydrationDone = false; | ||
| _doneValue = false; | ||
| _pendingBoundaries = 0; | ||
| signals.setSnapshotCapture(true); | ||
| _snapshotRootOwner = null; | ||
| } else if (was && !v) { | ||
| if (_snapshotRootOwner) { | ||
| signals.releaseSnapshotScope(_snapshotRootOwner); | ||
| _snapshotRootOwner = null; | ||
| } | ||
| checkHydrationComplete(); | ||
| } | ||
| }, | ||
| configurable: true, | ||
| enumerable: true | ||
| }); | ||
| Object.defineProperty(sharedConfig, "done", { | ||
| get() { | ||
| return _doneValue; | ||
| }, | ||
| set(v) { | ||
| _doneValue = v; | ||
| if (v) drainHydrationCallbacks(); | ||
| }, | ||
| configurable: true, | ||
| enumerable: true | ||
| }); | ||
| } | ||
| const createMemo = (...args) => (_createMemo || signals.createMemo)(...args); | ||
| const createSignal = (...args) => (_createSignal || signals.createSignal)(...args); | ||
| const createErrorBoundary = (...args) => (_createErrorBoundary || signals.createErrorBoundary)(...args); | ||
| const createOptimistic = (...args) => (_createOptimistic || signals.createOptimistic)(...args); | ||
| const createProjection = (...args) => (_createProjection || signals.createProjection)(...args); | ||
| const createStore = (...args) => (_createStore || signals.createStore)(...args); | ||
| const createOptimisticStore = (...args) => (_createOptimisticStore || signals.createOptimisticStore)(...args); | ||
| function loadModuleAssets(mapping) { | ||
| const hy = globalThis._$HY; | ||
| if (!hy) return; | ||
| if (!hy.modules) hy.modules = {}; | ||
| if (!hy.loading) hy.loading = {}; | ||
| const pending = []; | ||
| for (const moduleUrl in mapping) { | ||
| if (hy.modules[moduleUrl]) continue; | ||
| const entryUrl = mapping[moduleUrl]; | ||
| if (!hy.loading[moduleUrl]) { | ||
| hy.loading[moduleUrl] = import(entryUrl).then(mod => { | ||
| hy.modules[moduleUrl] = mod; | ||
| }); | ||
| } | ||
| pending.push(hy.loading[moduleUrl]); | ||
| } | ||
| return pending.length ? Promise.all(pending).then(() => {}) : undefined; | ||
| } | ||
| function createBoundaryTrigger() { | ||
| signals.setSnapshotCapture(false); | ||
| const [s, set] = signals.createSignal(undefined, { | ||
| equals: false | ||
| }); | ||
| s(); | ||
| signals.setSnapshotCapture(true); | ||
| return set; | ||
| } | ||
| function resumeBoundaryHydration(o, id, set) { | ||
| _pendingBoundaries--; | ||
| if (signals.isDisposed(o)) { | ||
| checkHydrationComplete(); | ||
| return; | ||
| } | ||
| sharedConfig.gather(id); | ||
| _hydratingValue = true; | ||
| signals.markSnapshotScope(o); | ||
| _snapshotRootOwner = o; | ||
| set(); | ||
| signals.flush(); | ||
| _snapshotRootOwner = null; | ||
| _hydratingValue = false; | ||
| signals.releaseSnapshotScope(o); | ||
| signals.flush(); | ||
| checkHydrationComplete(); | ||
| } | ||
| function Loading(props) { | ||
@@ -145,2 +497,7 @@ if (!sharedConfig.hydrating) return signals.createLoadBoundary(() => props.children, () => props.fallback); | ||
| const id = o.id; | ||
| let assetPromise; | ||
| if (sharedConfig.hydrating && sharedConfig.has(id + "_assets")) { | ||
| const mapping = sharedConfig.load(id + "_assets"); | ||
| if (mapping && typeof mapping === "object") assetPromise = loadModuleAssets(mapping); | ||
| } | ||
| if (sharedConfig.hydrating && sharedConfig.has(id)) { | ||
@@ -153,20 +510,34 @@ let ref = sharedConfig.load(id); | ||
| if (p) { | ||
| const [s, set] = signals.createSignal(undefined, { | ||
| equals: false | ||
| _pendingBoundaries++; | ||
| signals.onCleanup(() => { | ||
| if (!signals.isDisposed(o)) return; | ||
| sharedConfig.cleanupFragment?.(id); | ||
| }); | ||
| s(); | ||
| const set = createBoundaryTrigger(); | ||
| if (p !== "$$f") { | ||
| p.then(() => { | ||
| sharedConfig.gather(id); | ||
| sharedConfig.hydrating = true; | ||
| const waitFor = assetPromise ? Promise.all([p, assetPromise]) : p; | ||
| waitFor.then(() => resumeBoundaryHydration(o, id, set), err => { | ||
| _pendingBoundaries--; | ||
| checkHydrationComplete(); | ||
| signals.runWithOwner(o, () => { | ||
| throw err; | ||
| }); | ||
| }); | ||
| } else { | ||
| const afterAssets = () => { | ||
| _pendingBoundaries--; | ||
| set(); | ||
| signals.flush(); | ||
| sharedConfig.hydrating = false; | ||
| }, err => signals.runWithOwner(o, () => { | ||
| throw err; | ||
| })); | ||
| } else queueMicrotask(set); | ||
| checkHydrationComplete(); | ||
| }; | ||
| if (assetPromise) assetPromise.then(() => queueMicrotask(afterAssets));else queueMicrotask(afterAssets); | ||
| } | ||
| return props.fallback; | ||
| } | ||
| } | ||
| if (assetPromise) { | ||
| _pendingBoundaries++; | ||
| const set = createBoundaryTrigger(); | ||
| assetPromise.then(() => resumeBoundaryHydration(o, id, set)); | ||
| return undefined; | ||
| } | ||
| return signals.createLoadBoundary(() => props.children, () => props.fallback); | ||
@@ -179,7 +550,20 @@ }); | ||
| } | ||
| function lazy(fn) { | ||
| function lazy(fn, moduleUrl) { | ||
| let comp; | ||
| let p; | ||
| const wrap = props => { | ||
| comp = signals.createMemo(() => (p || (p = fn())).then(mod => mod.default)); | ||
| if (sharedConfig.hydrating && moduleUrl) { | ||
| const cached = globalThis._$HY?.modules?.[moduleUrl]; | ||
| if (!cached) { | ||
| throw new Error(`lazy() module "${moduleUrl}" was not preloaded before hydration. ` + "Ensure it is inside a Loading boundary."); | ||
| } | ||
| comp = () => cached.default; | ||
| } | ||
| if (!comp) { | ||
| p || (p = fn()); | ||
| p.then(mod => { | ||
| comp = () => mod.default; | ||
| }); | ||
| comp = signals.createMemo(() => p.then(mod => mod.default)); | ||
| } | ||
| let Comp; | ||
@@ -209,2 +593,3 @@ return signals.createMemo(() => (Comp = comp()) ? signals.untrack(() => { | ||
| }; | ||
| options.name = "<For>"; | ||
| return signals.mapArray(() => props.each, props.children, options); | ||
@@ -217,2 +602,3 @@ } | ||
| options.from = () => props.from; | ||
| options.name = "<Repeat>"; | ||
| return signals.repeat(() => props.count, index => typeof props.children === "function" ? props.children(index) : props.children, options); | ||
@@ -234,6 +620,13 @@ } | ||
| const fn = typeof child === "function" && child.length > 0; | ||
| return fn ? signals.untrack(() => child(() => { | ||
| if (!signals.untrack(condition)) throw narrowedError("Show"); | ||
| return conditionValue(); | ||
| })) : child; | ||
| return fn ? signals.untrack(() => { | ||
| signals.setStrictRead("<Show>"); | ||
| try { | ||
| return child(() => { | ||
| if (!signals.untrack(condition)) throw narrowedError("Show"); | ||
| return conditionValue(); | ||
| }); | ||
| } finally { | ||
| signals.setStrictRead(false); | ||
| } | ||
| }) : child; | ||
| } | ||
@@ -271,6 +664,13 @@ return props.fallback; | ||
| const fn = typeof child === "function" && child.length > 0; | ||
| return fn ? signals.untrack(() => child(() => { | ||
| if (signals.untrack(switchFunc)()?.[0] !== index) throw narrowedError("Match"); | ||
| return conditionValue(); | ||
| })) : child; | ||
| return fn ? signals.untrack(() => { | ||
| signals.setStrictRead("<Match>"); | ||
| try { | ||
| return child(() => { | ||
| if (signals.untrack(switchFunc)()?.[0] !== index) throw narrowedError("Match"); | ||
| return conditionValue(); | ||
| }); | ||
| } finally { | ||
| signals.setStrictRead(false); | ||
| } | ||
| }) : child; | ||
| }, undefined, { | ||
@@ -284,3 +684,3 @@ name: "eval conditions" | ||
| function Errored(props) { | ||
| return signals.createErrorBoundary(() => props.children, (err, reset) => { | ||
| return createErrorBoundary(() => props.children, (err, reset) => { | ||
| const f = props.fallback; | ||
@@ -323,14 +723,2 @@ if ((typeof f !== "function" || f.length == 0)) console.error(err); | ||
| }); | ||
| Object.defineProperty(exports, "createOptimistic", { | ||
| enumerable: true, | ||
| get: function () { return signals.createOptimistic; } | ||
| }); | ||
| Object.defineProperty(exports, "createOptimisticStore", { | ||
| enumerable: true, | ||
| get: function () { return signals.createOptimisticStore; } | ||
| }); | ||
| Object.defineProperty(exports, "createProjection", { | ||
| enumerable: true, | ||
| get: function () { return signals.createProjection; } | ||
| }); | ||
| Object.defineProperty(exports, "createReaction", { | ||
@@ -348,6 +736,2 @@ enumerable: true, | ||
| }); | ||
| Object.defineProperty(exports, "createStore", { | ||
| enumerable: true, | ||
| get: function () { return signals.createStore; } | ||
| }); | ||
| Object.defineProperty(exports, "createTrackedEffect", { | ||
@@ -458,3 +842,7 @@ enumerable: true, | ||
| exports.createMemo = createMemo; | ||
| exports.createOptimistic = createOptimistic; | ||
| exports.createOptimisticStore = createOptimisticStore; | ||
| exports.createProjection = createProjection; | ||
| exports.createSignal = createSignal; | ||
| exports.createStore = createStore; | ||
| exports.createUniqueId = createUniqueId; | ||
@@ -461,0 +849,0 @@ exports.enableHydration = enableHydration; |
+427
-27
@@ -1,3 +0,3 @@ | ||
| import { getContext, createMemo as createMemo$1, flatten, createRoot, setContext, getOwner, untrack, getNextChildId, createSignal as createSignal$1, createLoadBoundary, flush, runWithOwner, mapArray, repeat, createErrorBoundary } from '@solidjs/signals'; | ||
| export { $PROXY, $TRACK, NotReadyError, action, createEffect, createOptimistic, createOptimisticStore, createProjection, createReaction, createRenderEffect, createRoot, createStore, createTrackedEffect, deep, flatten, flush, getObserver, getOwner, isEqual, isPending, isRefreshing, isWrappable, mapArray, merge, omit, onCleanup, onSettled, pending, reconcile, refresh, repeat, resolve, runWithOwner, snapshot, untrack } from '@solidjs/signals'; | ||
| import { getContext, createMemo as createMemo$1, flatten, getOwner, createRoot, setContext, untrack, setStrictRead, createLoadBoundary, onCleanup, isDisposed, runWithOwner, createOptimistic as createOptimistic$1, createOptimisticStore as createOptimisticStore$1, createProjection as createProjection$1, createSignal as createSignal$1, createStore as createStore$1, setSnapshotCapture, releaseSnapshotScope, getNextChildId, createErrorBoundary as createErrorBoundary$1, markSnapshotScope, flush, clearSnapshots, peekNextChildId, mapArray, repeat } from '@solidjs/signals'; | ||
| export { $PROXY, $TRACK, NotReadyError, action, createEffect, createReaction, createRenderEffect, createRoot, createTrackedEffect, deep, flatten, flush, getObserver, getOwner, isEqual, isPending, isRefreshing, isWrappable, mapArray, merge, omit, onCleanup, onSettled, pending, reconcile, refresh, repeat, resolve, runWithOwner, snapshot, untrack } from '@solidjs/signals'; | ||
@@ -41,4 +41,11 @@ const $DEVCOMP = Symbol("COMPONENT_DEV" ); | ||
| }); | ||
| return Comp(props); | ||
| setStrictRead(`<${Comp.name || "Anonymous"}>`); | ||
| try { | ||
| return Comp(props); | ||
| } finally { | ||
| setStrictRead(false); | ||
| } | ||
| }); | ||
| }, { | ||
| transparent: true | ||
| }); | ||
@@ -63,4 +70,40 @@ } | ||
| }; | ||
| let _hydrationEndCallbacks = null; | ||
| let _pendingBoundaries = 0; | ||
| let _hydrationDone = false; | ||
| let _snapshotRootOwner = null; | ||
| function markTopLevelSnapshotScope() { | ||
| if (_snapshotRootOwner) return; | ||
| let owner = getOwner(); | ||
| if (!owner) return; | ||
| while (owner._parent) owner = owner._parent; | ||
| markSnapshotScope(owner); | ||
| _snapshotRootOwner = owner; | ||
| } | ||
| function drainHydrationCallbacks() { | ||
| if (_hydrationDone) return; | ||
| _hydrationDone = true; | ||
| _doneValue = true; | ||
| clearSnapshots(); | ||
| setSnapshotCapture(false); | ||
| flush(); | ||
| const cbs = _hydrationEndCallbacks; | ||
| _hydrationEndCallbacks = null; | ||
| if (cbs) for (const cb of cbs) cb(); | ||
| setTimeout(() => { | ||
| if (globalThis._$HY) globalThis._$HY.done = true; | ||
| }); | ||
| } | ||
| function checkHydrationComplete() { | ||
| if (_pendingBoundaries === 0) drainHydrationCallbacks(); | ||
| } | ||
| let _hydratingValue = false; | ||
| let _doneValue = false; | ||
| let _createMemo; | ||
| let _createSignal; | ||
| let _createErrorBoundary; | ||
| let _createOptimistic; | ||
| let _createProjection; | ||
| let _createStore; | ||
| let _createOptimisticStore; | ||
| class MockPromise { | ||
@@ -101,3 +144,7 @@ static all() { | ||
| Promise = MockPromise; | ||
| return fn(prev); | ||
| const result = fn(prev); | ||
| if (result && typeof result[Symbol.asyncIterator] === "function") { | ||
| result[Symbol.asyncIterator]().next(); | ||
| } | ||
| return result; | ||
| } finally { | ||
@@ -108,4 +155,96 @@ window.fetch = ogFetch; | ||
| } | ||
| function consumeFirstSync(ai) { | ||
| const iter = ai[Symbol.asyncIterator](); | ||
| const r = iter.next(); | ||
| const value = !(r instanceof Promise) && !r.done ? r.value : undefined; | ||
| return [value, iter]; | ||
| } | ||
| function applyPatches(target, patches) { | ||
| for (const patch of patches) { | ||
| const path = patch[0]; | ||
| let current = target; | ||
| for (let i = 0; i < path.length - 1; i++) current = current[path[i]]; | ||
| const key = path[path.length - 1]; | ||
| if (patch.length === 1) { | ||
| Array.isArray(current) ? current.splice(key, 1) : delete current[key]; | ||
| } else if (patch.length === 3) { | ||
| current.splice(key, 0, patch[1]); | ||
| } else { | ||
| current[key] = patch[1]; | ||
| } | ||
| } | ||
| } | ||
| function scheduleIteratorConsumption(iter, apply) { | ||
| const consume = () => { | ||
| while (true) { | ||
| const n = iter.next(); | ||
| if (n instanceof Promise) { | ||
| n.then(r => { | ||
| if (r.done) return; | ||
| apply(r.value); | ||
| consume(); | ||
| }); | ||
| return; | ||
| } | ||
| if (n.done) break; | ||
| apply(n.value); | ||
| } | ||
| }; | ||
| consume(); | ||
| } | ||
| function isAsyncIterable(v) { | ||
| return v != null && typeof v[Symbol.asyncIterator] === "function"; | ||
| } | ||
| function hydrateSignalFromAsyncIterable(coreFn, compute, value, options) { | ||
| const parent = getOwner(); | ||
| const expectedId = peekNextChildId(parent); | ||
| if (!sharedConfig.has(expectedId)) return null; | ||
| const initP = sharedConfig.load(expectedId); | ||
| if (!isAsyncIterable(initP)) return null; | ||
| const [firstValue, iter] = consumeFirstSync(initP); | ||
| const [get, set] = createSignal$1(firstValue); | ||
| const result = coreFn(() => get(), firstValue, options); | ||
| scheduleIteratorConsumption(iter, v => { | ||
| set(() => v); | ||
| flush(); | ||
| }); | ||
| return result; | ||
| } | ||
| function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) { | ||
| const parent = getOwner(); | ||
| const expectedId = peekNextChildId(parent); | ||
| if (!sharedConfig.has(expectedId)) return null; | ||
| const initP = sharedConfig.load(expectedId); | ||
| if (!isAsyncIterable(initP)) return null; | ||
| const [firstState, iter] = consumeFirstSync(initP); | ||
| const [store, setStore] = coreFn(() => {}, firstState ?? initialValue, options); | ||
| scheduleIteratorConsumption(iter, patches => { | ||
| setStore(d => { | ||
| applyPatches(d, patches); | ||
| }); | ||
| }); | ||
| return [store, setStore]; | ||
| } | ||
| function hydratedCreateMemo(compute, value, options) { | ||
| if (!sharedConfig.hydrating) return createMemo$1(compute, value, options); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = options?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = createSignal$1(false); | ||
| const memo = createMemo$1(prev => { | ||
| if (!hydrated()) return prev ?? value; | ||
| return compute(prev); | ||
| }, value, options); | ||
| setHydrated(true); | ||
| return memo; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return createMemo$1(prev => { | ||
| if (!sharedConfig.hydrating) return compute(prev); | ||
| subFetch(compute, prev); | ||
| return prev ?? value; | ||
| }, value, options); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(createMemo$1, compute, value, options); | ||
| if (aiResult !== null) return aiResult; | ||
| return createMemo$1(prev => { | ||
@@ -122,2 +261,22 @@ const o = getOwner(); | ||
| if (typeof fn !== "function" || !sharedConfig.hydrating) return createSignal$1(fn, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = createSignal$1(false); | ||
| const sig = createSignal$1(prev => { | ||
| if (!hydrated()) return prev ?? second; | ||
| return fn(prev); | ||
| }, second, third); | ||
| setHydrated(true); | ||
| return sig; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return createSignal$1(prev => { | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| subFetch(fn, prev); | ||
| return prev ?? second; | ||
| }, second, third); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(createSignal$1, fn, second, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return createSignal$1(prev => { | ||
@@ -132,8 +291,201 @@ if (!sharedConfig.hydrating) return fn(prev); | ||
| } | ||
| function hydratedCreateErrorBoundary(fn, fallback) { | ||
| if (!sharedConfig.hydrating) return createErrorBoundary$1(fn, fallback); | ||
| markTopLevelSnapshotScope(); | ||
| const parent = getOwner(); | ||
| const expectedId = peekNextChildId(parent); | ||
| if (sharedConfig.has(expectedId)) { | ||
| const err = sharedConfig.load(expectedId); | ||
| if (err !== undefined) { | ||
| let hydrated = true; | ||
| return createErrorBoundary$1(() => { | ||
| if (hydrated) { | ||
| hydrated = false; | ||
| throw err; | ||
| } | ||
| return fn(); | ||
| }, fallback); | ||
| } | ||
| } | ||
| return createErrorBoundary$1(fn, fallback); | ||
| } | ||
| function hydratedCreateOptimistic(fn, second, third) { | ||
| if (typeof fn !== "function" || !sharedConfig.hydrating) return createOptimistic$1(fn, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = createSignal$1(false); | ||
| const sig = createOptimistic$1(prev => { | ||
| if (!hydrated()) return prev ?? second; | ||
| return fn(prev); | ||
| }, second, third); | ||
| setHydrated(true); | ||
| return sig; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return createOptimistic$1(prev => { | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| subFetch(fn, prev); | ||
| return prev ?? second; | ||
| }, second, third); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(createOptimistic$1, fn, second, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return createOptimistic$1(prev => { | ||
| const o = getOwner(); | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| let initP; | ||
| if (sharedConfig.has(o.id)) initP = sharedConfig.load(o.id); | ||
| const init = initP?.v ?? initP; | ||
| return init != null ? (subFetch(fn, prev), init) : fn(prev); | ||
| }, second, third); | ||
| } | ||
| function wrapStoreFn(fn, ssrSource) { | ||
| if (ssrSource === "initial") { | ||
| return draft => { | ||
| if (!sharedConfig.hydrating) return fn(draft); | ||
| subFetch(fn, draft); | ||
| return undefined; | ||
| }; | ||
| } | ||
| return draft => { | ||
| const o = getOwner(); | ||
| if (!sharedConfig.hydrating) return fn(draft); | ||
| let initP; | ||
| if (sharedConfig.has(o.id)) initP = sharedConfig.load(o.id); | ||
| const init = initP?.v ?? initP; | ||
| return init != null ? (subFetch(fn, draft), init) : fn(draft); | ||
| }; | ||
| } | ||
| function hydratedCreateStore(first, second, third) { | ||
| if (typeof first !== "function" || !sharedConfig.hydrating) return createStore$1(first, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return createStore$1(second ?? {}, undefined, third); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(createStore$1, second ?? {}, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return createStore$1(wrapStoreFn(first, ssrSource), second, third); | ||
| } | ||
| function hydratedCreateOptimisticStore(first, second, third) { | ||
| if (typeof first !== "function" || !sharedConfig.hydrating) return createOptimisticStore$1(first, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return createOptimisticStore$1(second ?? {}, undefined, third); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(createOptimisticStore$1, second ?? {}, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return createOptimisticStore$1(wrapStoreFn(first, ssrSource), second, third); | ||
| } | ||
| function hydratedCreateProjection(fn, initialValue, options) { | ||
| if (!sharedConfig.hydrating) return createProjection$1(fn, initialValue, options); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = options?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return createProjection$1(draft => draft, initialValue, options); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(createStore$1, initialValue, options); | ||
| if (aiResult !== null) return aiResult[0]; | ||
| return createProjection$1(wrapStoreFn(fn, ssrSource), initialValue, options); | ||
| } | ||
| function enableHydration() { | ||
| _createMemo = hydratedCreateMemo; | ||
| _createSignal = hydratedCreateSignal; | ||
| _createErrorBoundary = hydratedCreateErrorBoundary; | ||
| _createOptimistic = hydratedCreateOptimistic; | ||
| _createProjection = hydratedCreateProjection; | ||
| _createStore = hydratedCreateStore; | ||
| _createOptimisticStore = hydratedCreateOptimisticStore; | ||
| _hydratingValue = sharedConfig.hydrating; | ||
| _doneValue = sharedConfig.done; | ||
| Object.defineProperty(sharedConfig, "hydrating", { | ||
| get() { | ||
| return _hydratingValue; | ||
| }, | ||
| set(v) { | ||
| const was = _hydratingValue; | ||
| _hydratingValue = v; | ||
| if (!was && v) { | ||
| _hydrationDone = false; | ||
| _doneValue = false; | ||
| _pendingBoundaries = 0; | ||
| setSnapshotCapture(true); | ||
| _snapshotRootOwner = null; | ||
| } else if (was && !v) { | ||
| if (_snapshotRootOwner) { | ||
| releaseSnapshotScope(_snapshotRootOwner); | ||
| _snapshotRootOwner = null; | ||
| } | ||
| checkHydrationComplete(); | ||
| } | ||
| }, | ||
| configurable: true, | ||
| enumerable: true | ||
| }); | ||
| Object.defineProperty(sharedConfig, "done", { | ||
| get() { | ||
| return _doneValue; | ||
| }, | ||
| set(v) { | ||
| _doneValue = v; | ||
| if (v) drainHydrationCallbacks(); | ||
| }, | ||
| configurable: true, | ||
| enumerable: true | ||
| }); | ||
| } | ||
| const createMemo = (...args) => (_createMemo || createMemo$1)(...args); | ||
| const createSignal = (...args) => (_createSignal || createSignal$1)(...args); | ||
| const createErrorBoundary = (...args) => (_createErrorBoundary || createErrorBoundary$1)(...args); | ||
| const createOptimistic = (...args) => (_createOptimistic || createOptimistic$1)(...args); | ||
| const createProjection = (...args) => (_createProjection || createProjection$1)(...args); | ||
| const createStore = (...args) => (_createStore || createStore$1)(...args); | ||
| const createOptimisticStore = (...args) => (_createOptimisticStore || createOptimisticStore$1)(...args); | ||
| function loadModuleAssets(mapping) { | ||
| const hy = globalThis._$HY; | ||
| if (!hy) return; | ||
| if (!hy.modules) hy.modules = {}; | ||
| if (!hy.loading) hy.loading = {}; | ||
| const pending = []; | ||
| for (const moduleUrl in mapping) { | ||
| if (hy.modules[moduleUrl]) continue; | ||
| const entryUrl = mapping[moduleUrl]; | ||
| if (!hy.loading[moduleUrl]) { | ||
| hy.loading[moduleUrl] = import(entryUrl).then(mod => { | ||
| hy.modules[moduleUrl] = mod; | ||
| }); | ||
| } | ||
| pending.push(hy.loading[moduleUrl]); | ||
| } | ||
| return pending.length ? Promise.all(pending).then(() => {}) : undefined; | ||
| } | ||
| function createBoundaryTrigger() { | ||
| setSnapshotCapture(false); | ||
| const [s, set] = createSignal$1(undefined, { | ||
| equals: false | ||
| }); | ||
| s(); | ||
| setSnapshotCapture(true); | ||
| return set; | ||
| } | ||
| function resumeBoundaryHydration(o, id, set) { | ||
| _pendingBoundaries--; | ||
| if (isDisposed(o)) { | ||
| checkHydrationComplete(); | ||
| return; | ||
| } | ||
| sharedConfig.gather(id); | ||
| _hydratingValue = true; | ||
| markSnapshotScope(o); | ||
| _snapshotRootOwner = o; | ||
| set(); | ||
| flush(); | ||
| _snapshotRootOwner = null; | ||
| _hydratingValue = false; | ||
| releaseSnapshotScope(o); | ||
| flush(); | ||
| checkHydrationComplete(); | ||
| } | ||
| function Loading(props) { | ||
@@ -144,2 +496,7 @@ if (!sharedConfig.hydrating) return createLoadBoundary(() => props.children, () => props.fallback); | ||
| const id = o.id; | ||
| let assetPromise; | ||
| if (sharedConfig.hydrating && sharedConfig.has(id + "_assets")) { | ||
| const mapping = sharedConfig.load(id + "_assets"); | ||
| if (mapping && typeof mapping === "object") assetPromise = loadModuleAssets(mapping); | ||
| } | ||
| if (sharedConfig.hydrating && sharedConfig.has(id)) { | ||
@@ -152,20 +509,34 @@ let ref = sharedConfig.load(id); | ||
| if (p) { | ||
| const [s, set] = createSignal$1(undefined, { | ||
| equals: false | ||
| _pendingBoundaries++; | ||
| onCleanup(() => { | ||
| if (!isDisposed(o)) return; | ||
| sharedConfig.cleanupFragment?.(id); | ||
| }); | ||
| s(); | ||
| const set = createBoundaryTrigger(); | ||
| if (p !== "$$f") { | ||
| p.then(() => { | ||
| sharedConfig.gather(id); | ||
| sharedConfig.hydrating = true; | ||
| const waitFor = assetPromise ? Promise.all([p, assetPromise]) : p; | ||
| waitFor.then(() => resumeBoundaryHydration(o, id, set), err => { | ||
| _pendingBoundaries--; | ||
| checkHydrationComplete(); | ||
| runWithOwner(o, () => { | ||
| throw err; | ||
| }); | ||
| }); | ||
| } else { | ||
| const afterAssets = () => { | ||
| _pendingBoundaries--; | ||
| set(); | ||
| flush(); | ||
| sharedConfig.hydrating = false; | ||
| }, err => runWithOwner(o, () => { | ||
| throw err; | ||
| })); | ||
| } else queueMicrotask(set); | ||
| checkHydrationComplete(); | ||
| }; | ||
| if (assetPromise) assetPromise.then(() => queueMicrotask(afterAssets));else queueMicrotask(afterAssets); | ||
| } | ||
| return props.fallback; | ||
| } | ||
| } | ||
| if (assetPromise) { | ||
| _pendingBoundaries++; | ||
| const set = createBoundaryTrigger(); | ||
| assetPromise.then(() => resumeBoundaryHydration(o, id, set)); | ||
| return undefined; | ||
| } | ||
| return createLoadBoundary(() => props.children, () => props.fallback); | ||
@@ -178,7 +549,20 @@ }); | ||
| } | ||
| function lazy(fn) { | ||
| function lazy(fn, moduleUrl) { | ||
| let comp; | ||
| let p; | ||
| const wrap = props => { | ||
| comp = createMemo$1(() => (p || (p = fn())).then(mod => mod.default)); | ||
| if (sharedConfig.hydrating && moduleUrl) { | ||
| const cached = globalThis._$HY?.modules?.[moduleUrl]; | ||
| if (!cached) { | ||
| throw new Error(`lazy() module "${moduleUrl}" was not preloaded before hydration. ` + "Ensure it is inside a Loading boundary."); | ||
| } | ||
| comp = () => cached.default; | ||
| } | ||
| if (!comp) { | ||
| p || (p = fn()); | ||
| p.then(mod => { | ||
| comp = () => mod.default; | ||
| }); | ||
| comp = createMemo$1(() => p.then(mod => mod.default)); | ||
| } | ||
| let Comp; | ||
@@ -208,2 +592,3 @@ return createMemo$1(() => (Comp = comp()) ? untrack(() => { | ||
| }; | ||
| options.name = "<For>"; | ||
| return mapArray(() => props.each, props.children, options); | ||
@@ -216,2 +601,3 @@ } | ||
| options.from = () => props.from; | ||
| options.name = "<Repeat>"; | ||
| return repeat(() => props.count, index => typeof props.children === "function" ? props.children(index) : props.children, options); | ||
@@ -233,6 +619,13 @@ } | ||
| const fn = typeof child === "function" && child.length > 0; | ||
| return fn ? untrack(() => child(() => { | ||
| if (!untrack(condition)) throw narrowedError("Show"); | ||
| return conditionValue(); | ||
| })) : child; | ||
| return fn ? untrack(() => { | ||
| setStrictRead("<Show>"); | ||
| try { | ||
| return child(() => { | ||
| if (!untrack(condition)) throw narrowedError("Show"); | ||
| return conditionValue(); | ||
| }); | ||
| } finally { | ||
| setStrictRead(false); | ||
| } | ||
| }) : child; | ||
| } | ||
@@ -270,6 +663,13 @@ return props.fallback; | ||
| const fn = typeof child === "function" && child.length > 0; | ||
| return fn ? untrack(() => child(() => { | ||
| if (untrack(switchFunc)()?.[0] !== index) throw narrowedError("Match"); | ||
| return conditionValue(); | ||
| })) : child; | ||
| return fn ? untrack(() => { | ||
| setStrictRead("<Match>"); | ||
| try { | ||
| return child(() => { | ||
| if (untrack(switchFunc)()?.[0] !== index) throw narrowedError("Match"); | ||
| return conditionValue(); | ||
| }); | ||
| } finally { | ||
| setStrictRead(false); | ||
| } | ||
| }) : child; | ||
| }, undefined, { | ||
@@ -301,2 +701,2 @@ name: "eval conditions" | ||
| export { $DEVCOMP, DEV, Errored, For, Loading, Match, Repeat, Show, Switch, children, createComponent, createContext, createMemo, createSignal, createUniqueId, enableHydration, lazy, sharedConfig, ssrHandleError, ssrRunInScope, useContext }; | ||
| export { $DEVCOMP, DEV, Errored, For, Loading, Match, Repeat, Show, Switch, children, createComponent, createContext, createMemo, createOptimistic, createOptimisticStore, createProjection, createSignal, createStore, createUniqueId, enableHydration, lazy, sharedConfig, ssrHandleError, ssrRunInScope, useContext }; |
+335
-43
@@ -28,2 +28,14 @@ 'use strict'; | ||
| if (typeof first === "function") { | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "initial" || ssrSource === "client") { | ||
| signals.createOwner(); | ||
| let value = second; | ||
| return [() => value, v => { | ||
| return value = typeof v === "function" ? v(value) : v; | ||
| }]; | ||
| } | ||
| const memoOpts = third?.deferStream || ssrSource ? { | ||
| deferStream: third?.deferStream, | ||
| ssrSource | ||
| } : undefined; | ||
| const memo = createMemo(p => { | ||
@@ -34,3 +46,3 @@ let value = first(p ? p[0]() : second); | ||
| }]; | ||
| }); | ||
| }, undefined, memoOpts); | ||
| return [() => memo()[0](), v => memo()[1](v)]; | ||
@@ -50,5 +62,10 @@ } | ||
| error: undefined, | ||
| computed: false | ||
| computed: false, | ||
| disposed: false | ||
| }; | ||
| signals.runWithOwner(owner, () => signals.onCleanup(() => { | ||
| comp.disposed = true; | ||
| })); | ||
| function update() { | ||
| if (comp.disposed) return; | ||
| try { | ||
@@ -58,3 +75,3 @@ comp.error = undefined; | ||
| comp.computed = true; | ||
| processResult(comp, result, owner, ctx); | ||
| processResult(comp, result, owner, ctx, options?.deferStream, options?.ssrSource); | ||
| } catch (err) { | ||
@@ -68,3 +85,6 @@ if (err instanceof signals.NotReadyError) { | ||
| } | ||
| if (!options?.lazy) { | ||
| const ssrSource = options?.ssrSource; | ||
| if (ssrSource === "initial" || ssrSource === "client") { | ||
| comp.computed = true; | ||
| } else if (!options?.lazy) { | ||
| update(); | ||
@@ -82,3 +102,64 @@ } | ||
| } | ||
| function processResult(comp, result, owner, ctx) { | ||
| function createDeepProxy(target, patches, basePath = []) { | ||
| const childProxies = new Map(); | ||
| const handler = { | ||
| get(obj, key, receiver) { | ||
| if (Array.isArray(obj)) { | ||
| if (key === "shift") { | ||
| return function () { | ||
| if (obj.length === 0) return undefined; | ||
| const removed = obj[0]; | ||
| Array.prototype.shift.call(obj); | ||
| childProxies.clear(); | ||
| patches.push([[...basePath, 0]]); | ||
| return removed; | ||
| }; | ||
| } | ||
| if (key === "unshift") { | ||
| return function (...items) { | ||
| const result = Array.prototype.unshift.apply(obj, items); | ||
| childProxies.clear(); | ||
| for (let i = 0; i < items.length; i++) { | ||
| patches.push([[...basePath, i], items[i], 1]); | ||
| } | ||
| return result; | ||
| }; | ||
| } | ||
| if (key === "splice") { | ||
| return function (start, deleteCount, ...items) { | ||
| const len = obj.length; | ||
| const s = start < 0 ? Math.max(len + start, 0) : Math.min(start, len); | ||
| const d = deleteCount === undefined ? len - s : Math.min(Math.max(deleteCount, 0), len - s); | ||
| const removed = Array.prototype.splice.apply(obj, [s, d, ...items]); | ||
| childProxies.clear(); | ||
| for (let i = 0; i < d; i++) patches.push([[...basePath, s]]); | ||
| for (let i = 0; i < items.length; i++) patches.push([[...basePath, s + i], items[i], 1]); | ||
| return removed; | ||
| }; | ||
| } | ||
| } | ||
| const value = Reflect.get(obj, key, receiver); | ||
| if (value !== null && typeof value === "object" && typeof key !== "symbol") { | ||
| if (!childProxies.has(key)) { | ||
| childProxies.set(key, createDeepProxy(value, patches, [...basePath, key])); | ||
| } | ||
| return childProxies.get(key); | ||
| } | ||
| return value; | ||
| }, | ||
| set(obj, key, value) { | ||
| childProxies.delete(key); | ||
| patches.push([[...basePath, key], value]); | ||
| return Reflect.set(obj, key, value); | ||
| }, | ||
| deleteProperty(obj, key) { | ||
| childProxies.delete(key); | ||
| patches.push([[...basePath, key]]); | ||
| return Reflect.deleteProperty(obj, key); | ||
| } | ||
| }; | ||
| return new Proxy(target, handler); | ||
| } | ||
| function processResult(comp, result, owner, ctx, deferStream, ssrSource) { | ||
| if (comp.disposed) return; | ||
| const id = owner.id; | ||
@@ -89,6 +170,8 @@ const uninitialized = comp.value === undefined; | ||
| result.s = 1; | ||
| result.v = comp.value = v; | ||
| result.v = v; | ||
| if (comp.disposed) return; | ||
| comp.value = v; | ||
| comp.error = undefined; | ||
| }); | ||
| if (ctx?.serialize && id) ctx.serialize(id, result); | ||
| }, () => {}); | ||
| if (ctx?.async && ctx.serialize && id) ctx.serialize(id, result, deferStream); | ||
| if (uninitialized) { | ||
@@ -102,10 +185,42 @@ comp.error = new signals.NotReadyError(result); | ||
| const iter = iterator.call(result); | ||
| const promise = iter.next().then(v => { | ||
| promise.s = 1; | ||
| promise.v = comp.value = v.value; | ||
| comp.error = undefined; | ||
| }); | ||
| if (ctx?.serialize && id) ctx.serialize(id, promise); | ||
| if (uninitialized) { | ||
| comp.error = new signals.NotReadyError(promise); | ||
| if (ssrSource === "hybrid") { | ||
| const promise = iter.next().then(v => { | ||
| promise.s = 1; | ||
| promise.v = v.value; | ||
| if (comp.disposed) return; | ||
| comp.value = v.value; | ||
| comp.error = undefined; | ||
| }, () => {}); | ||
| if (ctx?.async && ctx.serialize && id) ctx.serialize(id, promise, deferStream); | ||
| if (uninitialized) { | ||
| comp.error = new signals.NotReadyError(promise); | ||
| } | ||
| } else { | ||
| const firstNext = iter.next(); | ||
| const firstReady = firstNext.then(r => { | ||
| if (comp.disposed) return; | ||
| if (!r.done) { | ||
| comp.value = r.value; | ||
| comp.error = undefined; | ||
| } | ||
| }, () => {}); | ||
| let servedFirst = false; | ||
| const tapped = { | ||
| [Symbol.asyncIterator]: () => ({ | ||
| next() { | ||
| if (!servedFirst) { | ||
| servedFirst = true; | ||
| return firstNext.then(r => { | ||
| if (!r.done && !comp.disposed) comp.value = r.value; | ||
| return r; | ||
| }); | ||
| } | ||
| return iter.next().then(r => r); | ||
| } | ||
| }) | ||
| }; | ||
| if (ctx?.async && ctx.serialize && id) ctx.serialize(id, tapped, deferStream); | ||
| if (uninitialized) { | ||
| comp.error = new signals.NotReadyError(firstReady); | ||
| } | ||
| } | ||
@@ -128,3 +243,4 @@ return; | ||
| error: undefined, | ||
| computed: true | ||
| computed: true, | ||
| disposed: false | ||
| }, () => compute(value))); | ||
@@ -145,3 +261,3 @@ effectFn(result, value); | ||
| function createOptimistic(first, second, third) { | ||
| return createSignal(first, second); | ||
| return createSignal(first, second, third); | ||
| } | ||
@@ -154,12 +270,141 @@ function setProperty(state, property, value) { | ||
| } | ||
| function createStore(state) { | ||
| function setStore(fn) { | ||
| fn(state); | ||
| function createStore(first, second) { | ||
| if (typeof first === "function") { | ||
| const store = createProjection(first, second ?? {}); | ||
| return [store, fn => fn(store)]; | ||
| } | ||
| return [state, setStore]; | ||
| const state = first; | ||
| return [state, fn => fn(state)]; | ||
| } | ||
| const createOptimisticStore = createStore; | ||
| function createProjection(fn, initialValue = {}) { | ||
| function createPendingProxy(state, source) { | ||
| let pending = true; | ||
| let readTarget = state; | ||
| const proxy = new Proxy(state, { | ||
| get(obj, key, receiver) { | ||
| if (pending && typeof key !== "symbol") { | ||
| throw new signals.NotReadyError(source); | ||
| } | ||
| return Reflect.get(readTarget, key); | ||
| } | ||
| }); | ||
| return [proxy, frozen => { | ||
| if (frozen) readTarget = frozen; | ||
| pending = false; | ||
| }]; | ||
| } | ||
| function createProjection(fn, initialValue = {}, options) { | ||
| const ctx = sharedConfig.context; | ||
| const owner = signals.createOwner(); | ||
| const [state] = createStore(initialValue); | ||
| fn(state); | ||
| if (options?.ssrSource === "initial" || options?.ssrSource === "client") { | ||
| return state; | ||
| } | ||
| let disposed = false; | ||
| signals.runWithOwner(owner, () => signals.onCleanup(() => { | ||
| disposed = true; | ||
| })); | ||
| const ssrSource = options?.ssrSource; | ||
| const useProxy = ssrSource !== "hybrid"; | ||
| const patches = []; | ||
| const draft = useProxy ? createDeepProxy(state, patches) : state; | ||
| const result = signals.runWithOwner(owner, () => fn(draft)); | ||
| const iteratorFn = result?.[Symbol.asyncIterator]; | ||
| if (typeof iteratorFn === "function") { | ||
| const iter = iteratorFn.call(result); | ||
| if (ssrSource === "hybrid") { | ||
| const promise = iter.next().then(r => { | ||
| promise.s = 1; | ||
| if (disposed) { | ||
| promise.v = state; | ||
| return; | ||
| } | ||
| if (r.value !== undefined && r.value !== state) { | ||
| Object.assign(state, r.value); | ||
| } | ||
| promise.v = state; | ||
| markReady(); | ||
| }, () => {}); | ||
| if (ctx?.async && !ctx.noHydrate && owner.id) ctx.serialize(owner.id, promise, options?.deferStream); | ||
| const [pending, markReady] = createPendingProxy(state, promise); | ||
| return pending; | ||
| } else { | ||
| const firstNext = iter.next(); | ||
| const firstReady = firstNext.then(r => { | ||
| if (disposed) return; | ||
| patches.length = 0; | ||
| if (!r.done) { | ||
| if (r.value !== undefined && r.value !== draft) { | ||
| Object.assign(state, r.value); | ||
| } | ||
| } | ||
| markReady(JSON.parse(JSON.stringify(state))); | ||
| }, () => { | ||
| markReady(); | ||
| }); | ||
| let servedFirst = false; | ||
| const tapped = { | ||
| [Symbol.asyncIterator]: () => ({ | ||
| next() { | ||
| if (!servedFirst) { | ||
| servedFirst = true; | ||
| return firstNext.then(r => { | ||
| if (!r.done && !disposed) return { | ||
| done: false, | ||
| value: state | ||
| }; | ||
| return { | ||
| done: r.done, | ||
| value: undefined | ||
| }; | ||
| }); | ||
| } | ||
| return iter.next().then(r => { | ||
| if (disposed) return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| const flushed = patches.splice(0); | ||
| if (!r.done) { | ||
| if (r.value !== undefined && r.value !== draft) { | ||
| Object.assign(state, r.value); | ||
| } | ||
| return { | ||
| done: false, | ||
| value: flushed | ||
| }; | ||
| } | ||
| return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| }); | ||
| } | ||
| }) | ||
| }; | ||
| if (ctx?.async && !ctx.noHydrate && owner.id) ctx.serialize(owner.id, tapped, options?.deferStream); | ||
| const [pending, markReady] = createPendingProxy(state, firstReady); | ||
| return pending; | ||
| } | ||
| } | ||
| if (result instanceof Promise) { | ||
| const promise = result.then(v => { | ||
| promise.s = 1; | ||
| if (disposed) { | ||
| promise.v = state; | ||
| return; | ||
| } | ||
| if (v !== undefined && v !== state) { | ||
| Object.assign(state, v); | ||
| } | ||
| promise.v = state; | ||
| markReady(); | ||
| }, () => {}); | ||
| if (ctx?.async && !ctx.noHydrate && owner.id) ctx.serialize(owner.id, promise, options?.deferStream); | ||
| const [pending, markReady] = createPendingProxy(state, promise); | ||
| return pending; | ||
| } | ||
| if (result !== undefined && result !== state && result !== draft) { | ||
| Object.assign(state, result); | ||
| } | ||
| return state; | ||
@@ -216,2 +461,3 @@ } | ||
| function createErrorBoundary(fn, fallback) { | ||
| const ctx = sharedConfig.context; | ||
| const owner = signals.createOwner(); | ||
@@ -221,2 +467,3 @@ return signals.runWithOwner(owner, () => { | ||
| signals.setContext(ErrorContext, err => { | ||
| if (ctx && !ctx.noHydrate && owner.id) ctx.serialize(owner.id, err); | ||
| result = fallback(err, () => {}); | ||
@@ -227,2 +474,3 @@ }); | ||
| } catch (err) { | ||
| if (ctx && !ctx.noHydrate && owner.id) ctx.serialize(owner.id, err); | ||
| result = fallback(err, () => {}); | ||
@@ -316,5 +564,5 @@ } | ||
| } | ||
| function lazy(fn) { | ||
| function lazy(fn, moduleUrl) { | ||
| let p; | ||
| let load = id => { | ||
| let load = () => { | ||
| if (!p) { | ||
@@ -329,11 +577,26 @@ p = fn(); | ||
| const wrap = props => { | ||
| sharedConfig.getNextContextId(); | ||
| if (!moduleUrl) { | ||
| throw new Error("lazy() used in SSR without a moduleUrl. " + "All lazy() components require a moduleUrl for correct hydration. " + "This is typically injected by the bundler plugin."); | ||
| } | ||
| if (!sharedConfig.context?.resolveAssets) { | ||
| throw new Error(`lazy() called with moduleUrl "${moduleUrl}" but no asset manifest is set. ` + "Pass a manifest option to renderToStream/renderToString."); | ||
| } | ||
| load(); | ||
| if (p.v) return p.v(props); | ||
| if (sharedConfig.context?.async) { | ||
| sharedConfig.context.block(p.then(() => { | ||
| const ctx = sharedConfig.context; | ||
| if (!ctx?.registerAsset || !ctx.resolveAssets) return; | ||
| const assets = ctx.resolveAssets(moduleUrl); | ||
| if (assets) { | ||
| for (let i = 0; i < assets.css.length; i++) ctx.registerAsset("style", assets.css[i]); | ||
| for (let i = 0; i < assets.js.length; i++) ctx.registerAsset("module", assets.js[i]); | ||
| ctx.registerModule?.(moduleUrl, assets.js[0]); | ||
| } | ||
| if (ctx?.async) { | ||
| ctx.block(p.then(() => { | ||
| p.s = "success"; | ||
| })); | ||
| } | ||
| throw new signals.NotReadyError(p); | ||
| return createMemo(() => { | ||
| if (!p.v) throw new signals.NotReadyError(p); | ||
| return p.v(props); | ||
| }); | ||
| }; | ||
@@ -421,7 +684,15 @@ wrap.preload = load; | ||
| let runPromise; | ||
| let serializeBuffer = []; | ||
| const origSerialize = ctx.serialize; | ||
| function runInitially() { | ||
| o.dispose(false); | ||
| return signals.runWithOwner(o, () => { | ||
| serializeBuffer = []; | ||
| ctx.serialize = (id, p, deferStream) => { | ||
| serializeBuffer.push([id, p, deferStream]); | ||
| }; | ||
| const prevBoundary = ctx._currentBoundaryId; | ||
| ctx._currentBoundaryId = id; | ||
| const result = signals.runWithOwner(o, () => { | ||
| try { | ||
| return ctx.resolve(signals.flatten(props.children)); | ||
| return ctx.resolve(props.children); | ||
| } catch (err) { | ||
@@ -431,5 +702,14 @@ runPromise = ssrHandleError(err); | ||
| }); | ||
| ctx._currentBoundaryId = prevBoundary; | ||
| ctx.serialize = origSerialize; | ||
| return result; | ||
| } | ||
| let ret = runInitially(); | ||
| if (!(runPromise || ret?.p?.length)) return ret; | ||
| if (!(runPromise || ret?.p?.length)) { | ||
| for (const args of serializeBuffer) origSerialize(args[0], args[1], args[2]); | ||
| serializeBuffer = []; | ||
| const modules = ctx.getBoundaryModules?.(id); | ||
| if (modules) ctx.serialize(id + "_assets", modules); | ||
| return ret; | ||
| } | ||
| const fallbackOwner = signals.createOwner({ | ||
@@ -442,15 +722,26 @@ id | ||
| (async () => { | ||
| while (runPromise) { | ||
| await runPromise; | ||
| runPromise = undefined; | ||
| ret = runInitially(); | ||
| try { | ||
| while (runPromise) { | ||
| o.dispose(false); | ||
| await runPromise; | ||
| runPromise = undefined; | ||
| ret = runInitially(); | ||
| } | ||
| for (const args of serializeBuffer) origSerialize(args[0], args[1], args[2]); | ||
| serializeBuffer = []; | ||
| while (ret.p.length) { | ||
| await Promise.all(ret.p); | ||
| ret = signals.runWithOwner(o, () => ctx.ssr(ret.t, ...ret.h)); | ||
| } | ||
| done(ret.t[0]); | ||
| } catch (err) { | ||
| done(undefined, err); | ||
| } | ||
| while (ret.p.length) { | ||
| await Promise.all(ret.p); | ||
| ret = ctx.ssr(ret.t, ...ret.h); | ||
| } | ||
| done(ret.t[0]); | ||
| })(); | ||
| return signals.runWithOwner(fallbackOwner, () => ctx.ssr([`<template id="pl-${id}"></template>`, `<!--pl-${id}-->`], ctx.escape(props.fallback))); | ||
| } | ||
| for (const args of serializeBuffer) origSerialize(args[0], args[1], args[2]); | ||
| serializeBuffer = []; | ||
| const modules = ctx.getBoundaryModules?.(id); | ||
| if (modules) ctx.serialize(id + "_assets", modules); | ||
| ctx.serialize(id, "$$f"); | ||
@@ -527,2 +818,3 @@ return signals.runWithOwner(fallbackOwner, () => props.fallback); | ||
| exports.createContext = createContext; | ||
| exports.createDeepProxy = createDeepProxy; | ||
| exports.createEffect = createEffect; | ||
@@ -529,0 +821,0 @@ exports.createMemo = createMemo; |
+336
-45
@@ -1,2 +0,2 @@ | ||
| import { getOwner, getNextChildId, createOwner, runWithOwner, isWrappable, NotReadyError, setContext, getContext, createRoot, flatten } from '@solidjs/signals'; | ||
| import { getOwner, getNextChildId, createOwner, runWithOwner, onCleanup, NotReadyError, isWrappable, setContext, getContext, createRoot, flatten } from '@solidjs/signals'; | ||
| export { $PROXY, $TRACK, NotReadyError, createRoot, flatten, getOwner, isEqual, isWrappable, merge, omit, onCleanup, runWithOwner, snapshot } from '@solidjs/signals'; | ||
@@ -27,2 +27,14 @@ | ||
| if (typeof first === "function") { | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "initial" || ssrSource === "client") { | ||
| createOwner(); | ||
| let value = second; | ||
| return [() => value, v => { | ||
| return value = typeof v === "function" ? v(value) : v; | ||
| }]; | ||
| } | ||
| const memoOpts = third?.deferStream || ssrSource ? { | ||
| deferStream: third?.deferStream, | ||
| ssrSource | ||
| } : undefined; | ||
| const memo = createMemo(p => { | ||
@@ -33,3 +45,3 @@ let value = first(p ? p[0]() : second); | ||
| }]; | ||
| }); | ||
| }, undefined, memoOpts); | ||
| return [() => memo()[0](), v => memo()[1](v)]; | ||
@@ -49,5 +61,10 @@ } | ||
| error: undefined, | ||
| computed: false | ||
| computed: false, | ||
| disposed: false | ||
| }; | ||
| runWithOwner(owner, () => onCleanup(() => { | ||
| comp.disposed = true; | ||
| })); | ||
| function update() { | ||
| if (comp.disposed) return; | ||
| try { | ||
@@ -57,3 +74,3 @@ comp.error = undefined; | ||
| comp.computed = true; | ||
| processResult(comp, result, owner, ctx); | ||
| processResult(comp, result, owner, ctx, options?.deferStream, options?.ssrSource); | ||
| } catch (err) { | ||
@@ -67,3 +84,6 @@ if (err instanceof NotReadyError) { | ||
| } | ||
| if (!options?.lazy) { | ||
| const ssrSource = options?.ssrSource; | ||
| if (ssrSource === "initial" || ssrSource === "client") { | ||
| comp.computed = true; | ||
| } else if (!options?.lazy) { | ||
| update(); | ||
@@ -81,3 +101,64 @@ } | ||
| } | ||
| function processResult(comp, result, owner, ctx) { | ||
| function createDeepProxy(target, patches, basePath = []) { | ||
| const childProxies = new Map(); | ||
| const handler = { | ||
| get(obj, key, receiver) { | ||
| if (Array.isArray(obj)) { | ||
| if (key === "shift") { | ||
| return function () { | ||
| if (obj.length === 0) return undefined; | ||
| const removed = obj[0]; | ||
| Array.prototype.shift.call(obj); | ||
| childProxies.clear(); | ||
| patches.push([[...basePath, 0]]); | ||
| return removed; | ||
| }; | ||
| } | ||
| if (key === "unshift") { | ||
| return function (...items) { | ||
| const result = Array.prototype.unshift.apply(obj, items); | ||
| childProxies.clear(); | ||
| for (let i = 0; i < items.length; i++) { | ||
| patches.push([[...basePath, i], items[i], 1]); | ||
| } | ||
| return result; | ||
| }; | ||
| } | ||
| if (key === "splice") { | ||
| return function (start, deleteCount, ...items) { | ||
| const len = obj.length; | ||
| const s = start < 0 ? Math.max(len + start, 0) : Math.min(start, len); | ||
| const d = deleteCount === undefined ? len - s : Math.min(Math.max(deleteCount, 0), len - s); | ||
| const removed = Array.prototype.splice.apply(obj, [s, d, ...items]); | ||
| childProxies.clear(); | ||
| for (let i = 0; i < d; i++) patches.push([[...basePath, s]]); | ||
| for (let i = 0; i < items.length; i++) patches.push([[...basePath, s + i], items[i], 1]); | ||
| return removed; | ||
| }; | ||
| } | ||
| } | ||
| const value = Reflect.get(obj, key, receiver); | ||
| if (value !== null && typeof value === "object" && typeof key !== "symbol") { | ||
| if (!childProxies.has(key)) { | ||
| childProxies.set(key, createDeepProxy(value, patches, [...basePath, key])); | ||
| } | ||
| return childProxies.get(key); | ||
| } | ||
| return value; | ||
| }, | ||
| set(obj, key, value) { | ||
| childProxies.delete(key); | ||
| patches.push([[...basePath, key], value]); | ||
| return Reflect.set(obj, key, value); | ||
| }, | ||
| deleteProperty(obj, key) { | ||
| childProxies.delete(key); | ||
| patches.push([[...basePath, key]]); | ||
| return Reflect.deleteProperty(obj, key); | ||
| } | ||
| }; | ||
| return new Proxy(target, handler); | ||
| } | ||
| function processResult(comp, result, owner, ctx, deferStream, ssrSource) { | ||
| if (comp.disposed) return; | ||
| const id = owner.id; | ||
@@ -88,6 +169,8 @@ const uninitialized = comp.value === undefined; | ||
| result.s = 1; | ||
| result.v = comp.value = v; | ||
| result.v = v; | ||
| if (comp.disposed) return; | ||
| comp.value = v; | ||
| comp.error = undefined; | ||
| }); | ||
| if (ctx?.serialize && id) ctx.serialize(id, result); | ||
| }, () => {}); | ||
| if (ctx?.async && ctx.serialize && id) ctx.serialize(id, result, deferStream); | ||
| if (uninitialized) { | ||
@@ -101,10 +184,42 @@ comp.error = new NotReadyError(result); | ||
| const iter = iterator.call(result); | ||
| const promise = iter.next().then(v => { | ||
| promise.s = 1; | ||
| promise.v = comp.value = v.value; | ||
| comp.error = undefined; | ||
| }); | ||
| if (ctx?.serialize && id) ctx.serialize(id, promise); | ||
| if (uninitialized) { | ||
| comp.error = new NotReadyError(promise); | ||
| if (ssrSource === "hybrid") { | ||
| const promise = iter.next().then(v => { | ||
| promise.s = 1; | ||
| promise.v = v.value; | ||
| if (comp.disposed) return; | ||
| comp.value = v.value; | ||
| comp.error = undefined; | ||
| }, () => {}); | ||
| if (ctx?.async && ctx.serialize && id) ctx.serialize(id, promise, deferStream); | ||
| if (uninitialized) { | ||
| comp.error = new NotReadyError(promise); | ||
| } | ||
| } else { | ||
| const firstNext = iter.next(); | ||
| const firstReady = firstNext.then(r => { | ||
| if (comp.disposed) return; | ||
| if (!r.done) { | ||
| comp.value = r.value; | ||
| comp.error = undefined; | ||
| } | ||
| }, () => {}); | ||
| let servedFirst = false; | ||
| const tapped = { | ||
| [Symbol.asyncIterator]: () => ({ | ||
| next() { | ||
| if (!servedFirst) { | ||
| servedFirst = true; | ||
| return firstNext.then(r => { | ||
| if (!r.done && !comp.disposed) comp.value = r.value; | ||
| return r; | ||
| }); | ||
| } | ||
| return iter.next().then(r => r); | ||
| } | ||
| }) | ||
| }; | ||
| if (ctx?.async && ctx.serialize && id) ctx.serialize(id, tapped, deferStream); | ||
| if (uninitialized) { | ||
| comp.error = new NotReadyError(firstReady); | ||
| } | ||
| } | ||
@@ -127,3 +242,4 @@ return; | ||
| error: undefined, | ||
| computed: true | ||
| computed: true, | ||
| disposed: false | ||
| }, () => compute(value))); | ||
@@ -144,3 +260,3 @@ effectFn(result, value); | ||
| function createOptimistic(first, second, third) { | ||
| return createSignal(first, second); | ||
| return createSignal(first, second, third); | ||
| } | ||
@@ -153,12 +269,141 @@ function setProperty(state, property, value) { | ||
| } | ||
| function createStore(state) { | ||
| function setStore(fn) { | ||
| fn(state); | ||
| function createStore(first, second) { | ||
| if (typeof first === "function") { | ||
| const store = createProjection(first, second ?? {}); | ||
| return [store, fn => fn(store)]; | ||
| } | ||
| return [state, setStore]; | ||
| const state = first; | ||
| return [state, fn => fn(state)]; | ||
| } | ||
| const createOptimisticStore = createStore; | ||
| function createProjection(fn, initialValue = {}) { | ||
| function createPendingProxy(state, source) { | ||
| let pending = true; | ||
| let readTarget = state; | ||
| const proxy = new Proxy(state, { | ||
| get(obj, key, receiver) { | ||
| if (pending && typeof key !== "symbol") { | ||
| throw new NotReadyError(source); | ||
| } | ||
| return Reflect.get(readTarget, key); | ||
| } | ||
| }); | ||
| return [proxy, frozen => { | ||
| if (frozen) readTarget = frozen; | ||
| pending = false; | ||
| }]; | ||
| } | ||
| function createProjection(fn, initialValue = {}, options) { | ||
| const ctx = sharedConfig.context; | ||
| const owner = createOwner(); | ||
| const [state] = createStore(initialValue); | ||
| fn(state); | ||
| if (options?.ssrSource === "initial" || options?.ssrSource === "client") { | ||
| return state; | ||
| } | ||
| let disposed = false; | ||
| runWithOwner(owner, () => onCleanup(() => { | ||
| disposed = true; | ||
| })); | ||
| const ssrSource = options?.ssrSource; | ||
| const useProxy = ssrSource !== "hybrid"; | ||
| const patches = []; | ||
| const draft = useProxy ? createDeepProxy(state, patches) : state; | ||
| const result = runWithOwner(owner, () => fn(draft)); | ||
| const iteratorFn = result?.[Symbol.asyncIterator]; | ||
| if (typeof iteratorFn === "function") { | ||
| const iter = iteratorFn.call(result); | ||
| if (ssrSource === "hybrid") { | ||
| const promise = iter.next().then(r => { | ||
| promise.s = 1; | ||
| if (disposed) { | ||
| promise.v = state; | ||
| return; | ||
| } | ||
| if (r.value !== undefined && r.value !== state) { | ||
| Object.assign(state, r.value); | ||
| } | ||
| promise.v = state; | ||
| markReady(); | ||
| }, () => {}); | ||
| if (ctx?.async && !ctx.noHydrate && owner.id) ctx.serialize(owner.id, promise, options?.deferStream); | ||
| const [pending, markReady] = createPendingProxy(state, promise); | ||
| return pending; | ||
| } else { | ||
| const firstNext = iter.next(); | ||
| const firstReady = firstNext.then(r => { | ||
| if (disposed) return; | ||
| patches.length = 0; | ||
| if (!r.done) { | ||
| if (r.value !== undefined && r.value !== draft) { | ||
| Object.assign(state, r.value); | ||
| } | ||
| } | ||
| markReady(JSON.parse(JSON.stringify(state))); | ||
| }, () => { | ||
| markReady(); | ||
| }); | ||
| let servedFirst = false; | ||
| const tapped = { | ||
| [Symbol.asyncIterator]: () => ({ | ||
| next() { | ||
| if (!servedFirst) { | ||
| servedFirst = true; | ||
| return firstNext.then(r => { | ||
| if (!r.done && !disposed) return { | ||
| done: false, | ||
| value: state | ||
| }; | ||
| return { | ||
| done: r.done, | ||
| value: undefined | ||
| }; | ||
| }); | ||
| } | ||
| return iter.next().then(r => { | ||
| if (disposed) return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| const flushed = patches.splice(0); | ||
| if (!r.done) { | ||
| if (r.value !== undefined && r.value !== draft) { | ||
| Object.assign(state, r.value); | ||
| } | ||
| return { | ||
| done: false, | ||
| value: flushed | ||
| }; | ||
| } | ||
| return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| }); | ||
| } | ||
| }) | ||
| }; | ||
| if (ctx?.async && !ctx.noHydrate && owner.id) ctx.serialize(owner.id, tapped, options?.deferStream); | ||
| const [pending, markReady] = createPendingProxy(state, firstReady); | ||
| return pending; | ||
| } | ||
| } | ||
| if (result instanceof Promise) { | ||
| const promise = result.then(v => { | ||
| promise.s = 1; | ||
| if (disposed) { | ||
| promise.v = state; | ||
| return; | ||
| } | ||
| if (v !== undefined && v !== state) { | ||
| Object.assign(state, v); | ||
| } | ||
| promise.v = state; | ||
| markReady(); | ||
| }, () => {}); | ||
| if (ctx?.async && !ctx.noHydrate && owner.id) ctx.serialize(owner.id, promise, options?.deferStream); | ||
| const [pending, markReady] = createPendingProxy(state, promise); | ||
| return pending; | ||
| } | ||
| if (result !== undefined && result !== state && result !== draft) { | ||
| Object.assign(state, result); | ||
| } | ||
| return state; | ||
@@ -215,2 +460,3 @@ } | ||
| function createErrorBoundary(fn, fallback) { | ||
| const ctx = sharedConfig.context; | ||
| const owner = createOwner(); | ||
@@ -220,2 +466,3 @@ return runWithOwner(owner, () => { | ||
| setContext(ErrorContext, err => { | ||
| if (ctx && !ctx.noHydrate && owner.id) ctx.serialize(owner.id, err); | ||
| result = fallback(err, () => {}); | ||
@@ -226,2 +473,3 @@ }); | ||
| } catch (err) { | ||
| if (ctx && !ctx.noHydrate && owner.id) ctx.serialize(owner.id, err); | ||
| result = fallback(err, () => {}); | ||
@@ -315,5 +563,5 @@ } | ||
| } | ||
| function lazy(fn) { | ||
| function lazy(fn, moduleUrl) { | ||
| let p; | ||
| let load = id => { | ||
| let load = () => { | ||
| if (!p) { | ||
@@ -328,11 +576,26 @@ p = fn(); | ||
| const wrap = props => { | ||
| sharedConfig.getNextContextId(); | ||
| if (!moduleUrl) { | ||
| throw new Error("lazy() used in SSR without a moduleUrl. " + "All lazy() components require a moduleUrl for correct hydration. " + "This is typically injected by the bundler plugin."); | ||
| } | ||
| if (!sharedConfig.context?.resolveAssets) { | ||
| throw new Error(`lazy() called with moduleUrl "${moduleUrl}" but no asset manifest is set. ` + "Pass a manifest option to renderToStream/renderToString."); | ||
| } | ||
| load(); | ||
| if (p.v) return p.v(props); | ||
| if (sharedConfig.context?.async) { | ||
| sharedConfig.context.block(p.then(() => { | ||
| const ctx = sharedConfig.context; | ||
| if (!ctx?.registerAsset || !ctx.resolveAssets) return; | ||
| const assets = ctx.resolveAssets(moduleUrl); | ||
| if (assets) { | ||
| for (let i = 0; i < assets.css.length; i++) ctx.registerAsset("style", assets.css[i]); | ||
| for (let i = 0; i < assets.js.length; i++) ctx.registerAsset("module", assets.js[i]); | ||
| ctx.registerModule?.(moduleUrl, assets.js[0]); | ||
| } | ||
| if (ctx?.async) { | ||
| ctx.block(p.then(() => { | ||
| p.s = "success"; | ||
| })); | ||
| } | ||
| throw new NotReadyError(p); | ||
| return createMemo(() => { | ||
| if (!p.v) throw new NotReadyError(p); | ||
| return p.v(props); | ||
| }); | ||
| }; | ||
@@ -420,7 +683,15 @@ wrap.preload = load; | ||
| let runPromise; | ||
| let serializeBuffer = []; | ||
| const origSerialize = ctx.serialize; | ||
| function runInitially() { | ||
| o.dispose(false); | ||
| return runWithOwner(o, () => { | ||
| serializeBuffer = []; | ||
| ctx.serialize = (id, p, deferStream) => { | ||
| serializeBuffer.push([id, p, deferStream]); | ||
| }; | ||
| const prevBoundary = ctx._currentBoundaryId; | ||
| ctx._currentBoundaryId = id; | ||
| const result = runWithOwner(o, () => { | ||
| try { | ||
| return ctx.resolve(flatten(props.children)); | ||
| return ctx.resolve(props.children); | ||
| } catch (err) { | ||
@@ -430,5 +701,14 @@ runPromise = ssrHandleError(err); | ||
| }); | ||
| ctx._currentBoundaryId = prevBoundary; | ||
| ctx.serialize = origSerialize; | ||
| return result; | ||
| } | ||
| let ret = runInitially(); | ||
| if (!(runPromise || ret?.p?.length)) return ret; | ||
| if (!(runPromise || ret?.p?.length)) { | ||
| for (const args of serializeBuffer) origSerialize(args[0], args[1], args[2]); | ||
| serializeBuffer = []; | ||
| const modules = ctx.getBoundaryModules?.(id); | ||
| if (modules) ctx.serialize(id + "_assets", modules); | ||
| return ret; | ||
| } | ||
| const fallbackOwner = createOwner({ | ||
@@ -441,15 +721,26 @@ id | ||
| (async () => { | ||
| while (runPromise) { | ||
| await runPromise; | ||
| runPromise = undefined; | ||
| ret = runInitially(); | ||
| try { | ||
| while (runPromise) { | ||
| o.dispose(false); | ||
| await runPromise; | ||
| runPromise = undefined; | ||
| ret = runInitially(); | ||
| } | ||
| for (const args of serializeBuffer) origSerialize(args[0], args[1], args[2]); | ||
| serializeBuffer = []; | ||
| while (ret.p.length) { | ||
| await Promise.all(ret.p); | ||
| ret = runWithOwner(o, () => ctx.ssr(ret.t, ...ret.h)); | ||
| } | ||
| done(ret.t[0]); | ||
| } catch (err) { | ||
| done(undefined, err); | ||
| } | ||
| while (ret.p.length) { | ||
| await Promise.all(ret.p); | ||
| ret = ctx.ssr(ret.t, ...ret.h); | ||
| } | ||
| done(ret.t[0]); | ||
| })(); | ||
| return runWithOwner(fallbackOwner, () => ctx.ssr([`<template id="pl-${id}"></template>`, `<!--pl-${id}-->`], ctx.escape(props.fallback))); | ||
| } | ||
| for (const args of serializeBuffer) origSerialize(args[0], args[1], args[2]); | ||
| serializeBuffer = []; | ||
| const modules = ctx.getBoundaryModules?.(id); | ||
| if (modules) ctx.serialize(id + "_assets", modules); | ||
| ctx.serialize(id, "$$f"); | ||
@@ -461,2 +752,2 @@ return runWithOwner(fallbackOwner, () => props.fallback); | ||
| export { $DEVCOMP, DEV, Errored, For, Loading, Match, Repeat, Show, Switch, action, children, createComponent, createContext, createEffect, createMemo, createOptimistic, createOptimisticStore, createProjection, createReaction, createRenderEffect, createSignal, createStore, createTrackedEffect, createUniqueId, deep, enableHydration, flush, getObserver, isPending, isRefreshing, lazy, mapArray, onSettled, pending, reconcile, refresh, repeat, resolve, sharedConfig, ssrHandleError, ssrRunInScope, untrack, useContext }; | ||
| export { $DEVCOMP, DEV, Errored, For, Loading, Match, Repeat, Show, Switch, action, children, createComponent, createContext, createDeepProxy, createEffect, createMemo, createOptimistic, createOptimisticStore, createProjection, createReaction, createRenderEffect, createSignal, createStore, createTrackedEffect, createUniqueId, deep, enableHydration, flush, getObserver, isPending, isRefreshing, lazy, mapArray, onSettled, pending, reconcile, refresh, repeat, resolve, sharedConfig, ssrHandleError, ssrRunInScope, untrack, useContext }; |
+415
-40
@@ -41,4 +41,40 @@ 'use strict'; | ||
| }; | ||
| let _hydrationEndCallbacks = null; | ||
| let _pendingBoundaries = 0; | ||
| let _hydrationDone = false; | ||
| let _snapshotRootOwner = null; | ||
| function markTopLevelSnapshotScope() { | ||
| if (_snapshotRootOwner) return; | ||
| let owner = signals.getOwner(); | ||
| if (!owner) return; | ||
| while (owner._parent) owner = owner._parent; | ||
| signals.markSnapshotScope(owner); | ||
| _snapshotRootOwner = owner; | ||
| } | ||
| function drainHydrationCallbacks() { | ||
| if (_hydrationDone) return; | ||
| _hydrationDone = true; | ||
| _doneValue = true; | ||
| signals.clearSnapshots(); | ||
| signals.setSnapshotCapture(false); | ||
| signals.flush(); | ||
| const cbs = _hydrationEndCallbacks; | ||
| _hydrationEndCallbacks = null; | ||
| if (cbs) for (const cb of cbs) cb(); | ||
| setTimeout(() => { | ||
| if (globalThis._$HY) globalThis._$HY.done = true; | ||
| }); | ||
| } | ||
| function checkHydrationComplete() { | ||
| if (_pendingBoundaries === 0) drainHydrationCallbacks(); | ||
| } | ||
| let _hydratingValue = false; | ||
| let _doneValue = false; | ||
| let _createMemo; | ||
| let _createSignal; | ||
| let _createErrorBoundary; | ||
| let _createOptimistic; | ||
| let _createProjection; | ||
| let _createStore; | ||
| let _createOptimisticStore; | ||
| class MockPromise { | ||
@@ -79,3 +115,7 @@ static all() { | ||
| Promise = MockPromise; | ||
| return fn(prev); | ||
| const result = fn(prev); | ||
| if (result && typeof result[Symbol.asyncIterator] === "function") { | ||
| result[Symbol.asyncIterator]().next(); | ||
| } | ||
| return result; | ||
| } finally { | ||
@@ -86,4 +126,96 @@ window.fetch = ogFetch; | ||
| } | ||
| function consumeFirstSync(ai) { | ||
| const iter = ai[Symbol.asyncIterator](); | ||
| const r = iter.next(); | ||
| const value = !(r instanceof Promise) && !r.done ? r.value : undefined; | ||
| return [value, iter]; | ||
| } | ||
| function applyPatches(target, patches) { | ||
| for (const patch of patches) { | ||
| const path = patch[0]; | ||
| let current = target; | ||
| for (let i = 0; i < path.length - 1; i++) current = current[path[i]]; | ||
| const key = path[path.length - 1]; | ||
| if (patch.length === 1) { | ||
| Array.isArray(current) ? current.splice(key, 1) : delete current[key]; | ||
| } else if (patch.length === 3) { | ||
| current.splice(key, 0, patch[1]); | ||
| } else { | ||
| current[key] = patch[1]; | ||
| } | ||
| } | ||
| } | ||
| function scheduleIteratorConsumption(iter, apply) { | ||
| const consume = () => { | ||
| while (true) { | ||
| const n = iter.next(); | ||
| if (n instanceof Promise) { | ||
| n.then(r => { | ||
| if (r.done) return; | ||
| apply(r.value); | ||
| consume(); | ||
| }); | ||
| return; | ||
| } | ||
| if (n.done) break; | ||
| apply(n.value); | ||
| } | ||
| }; | ||
| consume(); | ||
| } | ||
| function isAsyncIterable(v) { | ||
| return v != null && typeof v[Symbol.asyncIterator] === "function"; | ||
| } | ||
| function hydrateSignalFromAsyncIterable(coreFn, compute, value, options) { | ||
| const parent = signals.getOwner(); | ||
| const expectedId = signals.peekNextChildId(parent); | ||
| if (!sharedConfig.has(expectedId)) return null; | ||
| const initP = sharedConfig.load(expectedId); | ||
| if (!isAsyncIterable(initP)) return null; | ||
| const [firstValue, iter] = consumeFirstSync(initP); | ||
| const [get, set] = signals.createSignal(firstValue); | ||
| const result = coreFn(() => get(), firstValue, options); | ||
| scheduleIteratorConsumption(iter, v => { | ||
| set(() => v); | ||
| signals.flush(); | ||
| }); | ||
| return result; | ||
| } | ||
| function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) { | ||
| const parent = signals.getOwner(); | ||
| const expectedId = signals.peekNextChildId(parent); | ||
| if (!sharedConfig.has(expectedId)) return null; | ||
| const initP = sharedConfig.load(expectedId); | ||
| if (!isAsyncIterable(initP)) return null; | ||
| const [firstState, iter] = consumeFirstSync(initP); | ||
| const [store, setStore] = coreFn(() => {}, firstState ?? initialValue, options); | ||
| scheduleIteratorConsumption(iter, patches => { | ||
| setStore(d => { | ||
| applyPatches(d, patches); | ||
| }); | ||
| }); | ||
| return [store, setStore]; | ||
| } | ||
| function hydratedCreateMemo(compute, value, options) { | ||
| if (!sharedConfig.hydrating) return signals.createMemo(compute, value, options); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = options?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = signals.createSignal(false); | ||
| const memo = signals.createMemo(prev => { | ||
| if (!hydrated()) return prev ?? value; | ||
| return compute(prev); | ||
| }, value, options); | ||
| setHydrated(true); | ||
| return memo; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return signals.createMemo(prev => { | ||
| if (!sharedConfig.hydrating) return compute(prev); | ||
| subFetch(compute, prev); | ||
| return prev ?? value; | ||
| }, value, options); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(signals.createMemo, compute, value, options); | ||
| if (aiResult !== null) return aiResult; | ||
| return signals.createMemo(prev => { | ||
@@ -100,2 +232,22 @@ const o = signals.getOwner(); | ||
| if (typeof fn !== "function" || !sharedConfig.hydrating) return signals.createSignal(fn, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = signals.createSignal(false); | ||
| const sig = signals.createSignal(prev => { | ||
| if (!hydrated()) return prev ?? second; | ||
| return fn(prev); | ||
| }, second, third); | ||
| setHydrated(true); | ||
| return sig; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return signals.createSignal(prev => { | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| subFetch(fn, prev); | ||
| return prev ?? second; | ||
| }, second, third); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(signals.createSignal, fn, second, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return signals.createSignal(prev => { | ||
@@ -110,8 +262,201 @@ if (!sharedConfig.hydrating) return fn(prev); | ||
| } | ||
| function hydratedCreateErrorBoundary(fn, fallback) { | ||
| if (!sharedConfig.hydrating) return signals.createErrorBoundary(fn, fallback); | ||
| markTopLevelSnapshotScope(); | ||
| const parent = signals.getOwner(); | ||
| const expectedId = signals.peekNextChildId(parent); | ||
| if (sharedConfig.has(expectedId)) { | ||
| const err = sharedConfig.load(expectedId); | ||
| if (err !== undefined) { | ||
| let hydrated = true; | ||
| return signals.createErrorBoundary(() => { | ||
| if (hydrated) { | ||
| hydrated = false; | ||
| throw err; | ||
| } | ||
| return fn(); | ||
| }, fallback); | ||
| } | ||
| } | ||
| return signals.createErrorBoundary(fn, fallback); | ||
| } | ||
| function hydratedCreateOptimistic(fn, second, third) { | ||
| if (typeof fn !== "function" || !sharedConfig.hydrating) return signals.createOptimistic(fn, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = signals.createSignal(false); | ||
| const sig = signals.createOptimistic(prev => { | ||
| if (!hydrated()) return prev ?? second; | ||
| return fn(prev); | ||
| }, second, third); | ||
| setHydrated(true); | ||
| return sig; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return signals.createOptimistic(prev => { | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| subFetch(fn, prev); | ||
| return prev ?? second; | ||
| }, second, third); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(signals.createOptimistic, fn, second, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return signals.createOptimistic(prev => { | ||
| const o = signals.getOwner(); | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| let initP; | ||
| if (sharedConfig.has(o.id)) initP = sharedConfig.load(o.id); | ||
| const init = initP?.v ?? initP; | ||
| return init != null ? (subFetch(fn, prev), init) : fn(prev); | ||
| }, second, third); | ||
| } | ||
| function wrapStoreFn(fn, ssrSource) { | ||
| if (ssrSource === "initial") { | ||
| return draft => { | ||
| if (!sharedConfig.hydrating) return fn(draft); | ||
| subFetch(fn, draft); | ||
| return undefined; | ||
| }; | ||
| } | ||
| return draft => { | ||
| const o = signals.getOwner(); | ||
| if (!sharedConfig.hydrating) return fn(draft); | ||
| let initP; | ||
| if (sharedConfig.has(o.id)) initP = sharedConfig.load(o.id); | ||
| const init = initP?.v ?? initP; | ||
| return init != null ? (subFetch(fn, draft), init) : fn(draft); | ||
| }; | ||
| } | ||
| function hydratedCreateStore(first, second, third) { | ||
| if (typeof first !== "function" || !sharedConfig.hydrating) return signals.createStore(first, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return signals.createStore(second ?? {}, undefined, third); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(signals.createStore, second ?? {}, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return signals.createStore(wrapStoreFn(first, ssrSource), second, third); | ||
| } | ||
| function hydratedCreateOptimisticStore(first, second, third) { | ||
| if (typeof first !== "function" || !sharedConfig.hydrating) return signals.createOptimisticStore(first, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return signals.createOptimisticStore(second ?? {}, undefined, third); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(signals.createOptimisticStore, second ?? {}, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return signals.createOptimisticStore(wrapStoreFn(first, ssrSource), second, third); | ||
| } | ||
| function hydratedCreateProjection(fn, initialValue, options) { | ||
| if (!sharedConfig.hydrating) return signals.createProjection(fn, initialValue, options); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = options?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return signals.createProjection(draft => draft, initialValue, options); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(signals.createStore, initialValue, options); | ||
| if (aiResult !== null) return aiResult[0]; | ||
| return signals.createProjection(wrapStoreFn(fn, ssrSource), initialValue, options); | ||
| } | ||
| function enableHydration() { | ||
| _createMemo = hydratedCreateMemo; | ||
| _createSignal = hydratedCreateSignal; | ||
| _createErrorBoundary = hydratedCreateErrorBoundary; | ||
| _createOptimistic = hydratedCreateOptimistic; | ||
| _createProjection = hydratedCreateProjection; | ||
| _createStore = hydratedCreateStore; | ||
| _createOptimisticStore = hydratedCreateOptimisticStore; | ||
| _hydratingValue = sharedConfig.hydrating; | ||
| _doneValue = sharedConfig.done; | ||
| Object.defineProperty(sharedConfig, "hydrating", { | ||
| get() { | ||
| return _hydratingValue; | ||
| }, | ||
| set(v) { | ||
| const was = _hydratingValue; | ||
| _hydratingValue = v; | ||
| if (!was && v) { | ||
| _hydrationDone = false; | ||
| _doneValue = false; | ||
| _pendingBoundaries = 0; | ||
| signals.setSnapshotCapture(true); | ||
| _snapshotRootOwner = null; | ||
| } else if (was && !v) { | ||
| if (_snapshotRootOwner) { | ||
| signals.releaseSnapshotScope(_snapshotRootOwner); | ||
| _snapshotRootOwner = null; | ||
| } | ||
| checkHydrationComplete(); | ||
| } | ||
| }, | ||
| configurable: true, | ||
| enumerable: true | ||
| }); | ||
| Object.defineProperty(sharedConfig, "done", { | ||
| get() { | ||
| return _doneValue; | ||
| }, | ||
| set(v) { | ||
| _doneValue = v; | ||
| if (v) drainHydrationCallbacks(); | ||
| }, | ||
| configurable: true, | ||
| enumerable: true | ||
| }); | ||
| } | ||
| const createMemo = (...args) => (_createMemo || signals.createMemo)(...args); | ||
| const createSignal = (...args) => (_createSignal || signals.createSignal)(...args); | ||
| const createErrorBoundary = (...args) => (_createErrorBoundary || signals.createErrorBoundary)(...args); | ||
| const createOptimistic = (...args) => (_createOptimistic || signals.createOptimistic)(...args); | ||
| const createProjection = (...args) => (_createProjection || signals.createProjection)(...args); | ||
| const createStore = (...args) => (_createStore || signals.createStore)(...args); | ||
| const createOptimisticStore = (...args) => (_createOptimisticStore || signals.createOptimisticStore)(...args); | ||
| function loadModuleAssets(mapping) { | ||
| const hy = globalThis._$HY; | ||
| if (!hy) return; | ||
| if (!hy.modules) hy.modules = {}; | ||
| if (!hy.loading) hy.loading = {}; | ||
| const pending = []; | ||
| for (const moduleUrl in mapping) { | ||
| if (hy.modules[moduleUrl]) continue; | ||
| const entryUrl = mapping[moduleUrl]; | ||
| if (!hy.loading[moduleUrl]) { | ||
| hy.loading[moduleUrl] = import(entryUrl).then(mod => { | ||
| hy.modules[moduleUrl] = mod; | ||
| }); | ||
| } | ||
| pending.push(hy.loading[moduleUrl]); | ||
| } | ||
| return pending.length ? Promise.all(pending).then(() => {}) : undefined; | ||
| } | ||
| function createBoundaryTrigger() { | ||
| signals.setSnapshotCapture(false); | ||
| const [s, set] = signals.createSignal(undefined, { | ||
| equals: false | ||
| }); | ||
| s(); | ||
| signals.setSnapshotCapture(true); | ||
| return set; | ||
| } | ||
| function resumeBoundaryHydration(o, id, set) { | ||
| _pendingBoundaries--; | ||
| if (signals.isDisposed(o)) { | ||
| checkHydrationComplete(); | ||
| return; | ||
| } | ||
| sharedConfig.gather(id); | ||
| _hydratingValue = true; | ||
| signals.markSnapshotScope(o); | ||
| _snapshotRootOwner = o; | ||
| set(); | ||
| signals.flush(); | ||
| _snapshotRootOwner = null; | ||
| _hydratingValue = false; | ||
| signals.releaseSnapshotScope(o); | ||
| signals.flush(); | ||
| checkHydrationComplete(); | ||
| } | ||
| function Loading(props) { | ||
@@ -122,2 +467,7 @@ if (!sharedConfig.hydrating) return signals.createLoadBoundary(() => props.children, () => props.fallback); | ||
| const id = o.id; | ||
| let assetPromise; | ||
| if (sharedConfig.hydrating && sharedConfig.has(id + "_assets")) { | ||
| const mapping = sharedConfig.load(id + "_assets"); | ||
| if (mapping && typeof mapping === "object") assetPromise = loadModuleAssets(mapping); | ||
| } | ||
| if (sharedConfig.hydrating && sharedConfig.has(id)) { | ||
@@ -130,20 +480,34 @@ let ref = sharedConfig.load(id); | ||
| if (p) { | ||
| const [s, set] = signals.createSignal(undefined, { | ||
| equals: false | ||
| _pendingBoundaries++; | ||
| signals.onCleanup(() => { | ||
| if (!signals.isDisposed(o)) return; | ||
| sharedConfig.cleanupFragment?.(id); | ||
| }); | ||
| s(); | ||
| const set = createBoundaryTrigger(); | ||
| if (p !== "$$f") { | ||
| p.then(() => { | ||
| sharedConfig.gather(id); | ||
| sharedConfig.hydrating = true; | ||
| const waitFor = assetPromise ? Promise.all([p, assetPromise]) : p; | ||
| waitFor.then(() => resumeBoundaryHydration(o, id, set), err => { | ||
| _pendingBoundaries--; | ||
| checkHydrationComplete(); | ||
| signals.runWithOwner(o, () => { | ||
| throw err; | ||
| }); | ||
| }); | ||
| } else { | ||
| const afterAssets = () => { | ||
| _pendingBoundaries--; | ||
| set(); | ||
| signals.flush(); | ||
| sharedConfig.hydrating = false; | ||
| }, err => signals.runWithOwner(o, () => { | ||
| throw err; | ||
| })); | ||
| } else queueMicrotask(set); | ||
| checkHydrationComplete(); | ||
| }; | ||
| if (assetPromise) assetPromise.then(() => queueMicrotask(afterAssets));else queueMicrotask(afterAssets); | ||
| } | ||
| return props.fallback; | ||
| } | ||
| } | ||
| if (assetPromise) { | ||
| _pendingBoundaries++; | ||
| const set = createBoundaryTrigger(); | ||
| assetPromise.then(() => resumeBoundaryHydration(o, id, set)); | ||
| return undefined; | ||
| } | ||
| return signals.createLoadBoundary(() => props.children, () => props.fallback); | ||
@@ -156,7 +520,20 @@ }); | ||
| } | ||
| function lazy(fn) { | ||
| function lazy(fn, moduleUrl) { | ||
| let comp; | ||
| let p; | ||
| const wrap = props => { | ||
| comp = signals.createMemo(() => (p || (p = fn())).then(mod => mod.default)); | ||
| if (sharedConfig.hydrating && moduleUrl) { | ||
| const cached = globalThis._$HY?.modules?.[moduleUrl]; | ||
| if (!cached) { | ||
| throw new Error(`lazy() module "${moduleUrl}" was not preloaded before hydration. ` + "Ensure it is inside a Loading boundary."); | ||
| } | ||
| comp = () => cached.default; | ||
| } | ||
| if (!comp) { | ||
| p || (p = fn()); | ||
| p.then(mod => { | ||
| comp = () => mod.default; | ||
| }); | ||
| comp = signals.createMemo(() => p.then(mod => mod.default)); | ||
| } | ||
| let Comp; | ||
@@ -203,6 +580,11 @@ return signals.createMemo(() => (Comp = comp()) ? signals.untrack(() => { | ||
| const fn = typeof child === "function" && child.length > 0; | ||
| return fn ? signals.untrack(() => child(() => { | ||
| if (!signals.untrack(condition)) throw narrowedError("Show"); | ||
| return conditionValue(); | ||
| })) : child; | ||
| return fn ? signals.untrack(() => { | ||
| try { | ||
| return child(() => { | ||
| if (!signals.untrack(condition)) throw narrowedError("Show"); | ||
| return conditionValue(); | ||
| }); | ||
| } finally { | ||
| } | ||
| }) : child; | ||
| } | ||
@@ -235,6 +617,11 @@ return props.fallback; | ||
| const fn = typeof child === "function" && child.length > 0; | ||
| return fn ? signals.untrack(() => child(() => { | ||
| if (signals.untrack(switchFunc)()?.[0] !== index) throw narrowedError("Match"); | ||
| return conditionValue(); | ||
| })) : child; | ||
| return fn ? signals.untrack(() => { | ||
| try { | ||
| return child(() => { | ||
| if (signals.untrack(switchFunc)()?.[0] !== index) throw narrowedError("Match"); | ||
| return conditionValue(); | ||
| }); | ||
| } finally { | ||
| } | ||
| }) : child; | ||
| }, undefined, undefined); | ||
@@ -246,3 +633,3 @@ } | ||
| function Errored(props) { | ||
| return signals.createErrorBoundary(() => props.children, (err, reset) => { | ||
| return createErrorBoundary(() => props.children, (err, reset) => { | ||
| const f = props.fallback; | ||
@@ -277,14 +664,2 @@ return typeof f === "function" && f.length ? f(err, reset) : f; | ||
| }); | ||
| Object.defineProperty(exports, "createOptimistic", { | ||
| enumerable: true, | ||
| get: function () { return signals.createOptimistic; } | ||
| }); | ||
| Object.defineProperty(exports, "createOptimisticStore", { | ||
| enumerable: true, | ||
| get: function () { return signals.createOptimisticStore; } | ||
| }); | ||
| Object.defineProperty(exports, "createProjection", { | ||
| enumerable: true, | ||
| get: function () { return signals.createProjection; } | ||
| }); | ||
| Object.defineProperty(exports, "createReaction", { | ||
@@ -302,6 +677,2 @@ enumerable: true, | ||
| }); | ||
| Object.defineProperty(exports, "createStore", { | ||
| enumerable: true, | ||
| get: function () { return signals.createStore; } | ||
| }); | ||
| Object.defineProperty(exports, "createTrackedEffect", { | ||
@@ -412,3 +783,7 @@ enumerable: true, | ||
| exports.createMemo = createMemo; | ||
| exports.createOptimistic = createOptimistic; | ||
| exports.createOptimisticStore = createOptimisticStore; | ||
| exports.createProjection = createProjection; | ||
| exports.createSignal = createSignal; | ||
| exports.createStore = createStore; | ||
| exports.createUniqueId = createUniqueId; | ||
@@ -415,0 +790,0 @@ exports.enableHydration = enableHydration; |
+413
-26
@@ -1,3 +0,3 @@ | ||
| import { getContext, createMemo as createMemo$1, flatten, createRoot, setContext, getOwner, getNextChildId, createSignal as createSignal$1, createLoadBoundary, flush, runWithOwner, untrack, mapArray, repeat, createErrorBoundary } from '@solidjs/signals'; | ||
| export { $PROXY, $TRACK, NotReadyError, action, createEffect, createOptimistic, createOptimisticStore, createProjection, createReaction, createRenderEffect, createRoot, createStore, createTrackedEffect, deep, flatten, flush, getObserver, getOwner, isEqual, isPending, isRefreshing, isWrappable, mapArray, merge, omit, onCleanup, onSettled, pending, reconcile, refresh, repeat, resolve, runWithOwner, snapshot, untrack } from '@solidjs/signals'; | ||
| import { getContext, createMemo as createMemo$1, flatten, createRoot, setContext, createLoadBoundary, getOwner, onCleanup, isDisposed, runWithOwner, createOptimistic as createOptimistic$1, createOptimisticStore as createOptimisticStore$1, createProjection as createProjection$1, createSignal as createSignal$1, createStore as createStore$1, setSnapshotCapture, releaseSnapshotScope, getNextChildId, createErrorBoundary as createErrorBoundary$1, markSnapshotScope, flush, clearSnapshots, peekNextChildId, untrack, mapArray, repeat } from '@solidjs/signals'; | ||
| export { $PROXY, $TRACK, NotReadyError, action, createEffect, createReaction, createRenderEffect, createRoot, createTrackedEffect, deep, flatten, flush, getObserver, getOwner, isEqual, isPending, isRefreshing, isWrappable, mapArray, merge, omit, onCleanup, onSettled, pending, reconcile, refresh, repeat, resolve, runWithOwner, snapshot, untrack } from '@solidjs/signals'; | ||
@@ -40,4 +40,40 @@ const $DEVCOMP = Symbol(0); | ||
| }; | ||
| let _hydrationEndCallbacks = null; | ||
| let _pendingBoundaries = 0; | ||
| let _hydrationDone = false; | ||
| let _snapshotRootOwner = null; | ||
| function markTopLevelSnapshotScope() { | ||
| if (_snapshotRootOwner) return; | ||
| let owner = getOwner(); | ||
| if (!owner) return; | ||
| while (owner._parent) owner = owner._parent; | ||
| markSnapshotScope(owner); | ||
| _snapshotRootOwner = owner; | ||
| } | ||
| function drainHydrationCallbacks() { | ||
| if (_hydrationDone) return; | ||
| _hydrationDone = true; | ||
| _doneValue = true; | ||
| clearSnapshots(); | ||
| setSnapshotCapture(false); | ||
| flush(); | ||
| const cbs = _hydrationEndCallbacks; | ||
| _hydrationEndCallbacks = null; | ||
| if (cbs) for (const cb of cbs) cb(); | ||
| setTimeout(() => { | ||
| if (globalThis._$HY) globalThis._$HY.done = true; | ||
| }); | ||
| } | ||
| function checkHydrationComplete() { | ||
| if (_pendingBoundaries === 0) drainHydrationCallbacks(); | ||
| } | ||
| let _hydratingValue = false; | ||
| let _doneValue = false; | ||
| let _createMemo; | ||
| let _createSignal; | ||
| let _createErrorBoundary; | ||
| let _createOptimistic; | ||
| let _createProjection; | ||
| let _createStore; | ||
| let _createOptimisticStore; | ||
| class MockPromise { | ||
@@ -78,3 +114,7 @@ static all() { | ||
| Promise = MockPromise; | ||
| return fn(prev); | ||
| const result = fn(prev); | ||
| if (result && typeof result[Symbol.asyncIterator] === "function") { | ||
| result[Symbol.asyncIterator]().next(); | ||
| } | ||
| return result; | ||
| } finally { | ||
@@ -85,4 +125,96 @@ window.fetch = ogFetch; | ||
| } | ||
| function consumeFirstSync(ai) { | ||
| const iter = ai[Symbol.asyncIterator](); | ||
| const r = iter.next(); | ||
| const value = !(r instanceof Promise) && !r.done ? r.value : undefined; | ||
| return [value, iter]; | ||
| } | ||
| function applyPatches(target, patches) { | ||
| for (const patch of patches) { | ||
| const path = patch[0]; | ||
| let current = target; | ||
| for (let i = 0; i < path.length - 1; i++) current = current[path[i]]; | ||
| const key = path[path.length - 1]; | ||
| if (patch.length === 1) { | ||
| Array.isArray(current) ? current.splice(key, 1) : delete current[key]; | ||
| } else if (patch.length === 3) { | ||
| current.splice(key, 0, patch[1]); | ||
| } else { | ||
| current[key] = patch[1]; | ||
| } | ||
| } | ||
| } | ||
| function scheduleIteratorConsumption(iter, apply) { | ||
| const consume = () => { | ||
| while (true) { | ||
| const n = iter.next(); | ||
| if (n instanceof Promise) { | ||
| n.then(r => { | ||
| if (r.done) return; | ||
| apply(r.value); | ||
| consume(); | ||
| }); | ||
| return; | ||
| } | ||
| if (n.done) break; | ||
| apply(n.value); | ||
| } | ||
| }; | ||
| consume(); | ||
| } | ||
| function isAsyncIterable(v) { | ||
| return v != null && typeof v[Symbol.asyncIterator] === "function"; | ||
| } | ||
| function hydrateSignalFromAsyncIterable(coreFn, compute, value, options) { | ||
| const parent = getOwner(); | ||
| const expectedId = peekNextChildId(parent); | ||
| if (!sharedConfig.has(expectedId)) return null; | ||
| const initP = sharedConfig.load(expectedId); | ||
| if (!isAsyncIterable(initP)) return null; | ||
| const [firstValue, iter] = consumeFirstSync(initP); | ||
| const [get, set] = createSignal$1(firstValue); | ||
| const result = coreFn(() => get(), firstValue, options); | ||
| scheduleIteratorConsumption(iter, v => { | ||
| set(() => v); | ||
| flush(); | ||
| }); | ||
| return result; | ||
| } | ||
| function hydrateStoreFromAsyncIterable(coreFn, initialValue, options) { | ||
| const parent = getOwner(); | ||
| const expectedId = peekNextChildId(parent); | ||
| if (!sharedConfig.has(expectedId)) return null; | ||
| const initP = sharedConfig.load(expectedId); | ||
| if (!isAsyncIterable(initP)) return null; | ||
| const [firstState, iter] = consumeFirstSync(initP); | ||
| const [store, setStore] = coreFn(() => {}, firstState ?? initialValue, options); | ||
| scheduleIteratorConsumption(iter, patches => { | ||
| setStore(d => { | ||
| applyPatches(d, patches); | ||
| }); | ||
| }); | ||
| return [store, setStore]; | ||
| } | ||
| function hydratedCreateMemo(compute, value, options) { | ||
| if (!sharedConfig.hydrating) return createMemo$1(compute, value, options); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = options?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = createSignal$1(false); | ||
| const memo = createMemo$1(prev => { | ||
| if (!hydrated()) return prev ?? value; | ||
| return compute(prev); | ||
| }, value, options); | ||
| setHydrated(true); | ||
| return memo; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return createMemo$1(prev => { | ||
| if (!sharedConfig.hydrating) return compute(prev); | ||
| subFetch(compute, prev); | ||
| return prev ?? value; | ||
| }, value, options); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(createMemo$1, compute, value, options); | ||
| if (aiResult !== null) return aiResult; | ||
| return createMemo$1(prev => { | ||
@@ -99,2 +231,22 @@ const o = getOwner(); | ||
| if (typeof fn !== "function" || !sharedConfig.hydrating) return createSignal$1(fn, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = createSignal$1(false); | ||
| const sig = createSignal$1(prev => { | ||
| if (!hydrated()) return prev ?? second; | ||
| return fn(prev); | ||
| }, second, third); | ||
| setHydrated(true); | ||
| return sig; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return createSignal$1(prev => { | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| subFetch(fn, prev); | ||
| return prev ?? second; | ||
| }, second, third); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(createSignal$1, fn, second, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return createSignal$1(prev => { | ||
@@ -109,8 +261,201 @@ if (!sharedConfig.hydrating) return fn(prev); | ||
| } | ||
| function hydratedCreateErrorBoundary(fn, fallback) { | ||
| if (!sharedConfig.hydrating) return createErrorBoundary$1(fn, fallback); | ||
| markTopLevelSnapshotScope(); | ||
| const parent = getOwner(); | ||
| const expectedId = peekNextChildId(parent); | ||
| if (sharedConfig.has(expectedId)) { | ||
| const err = sharedConfig.load(expectedId); | ||
| if (err !== undefined) { | ||
| let hydrated = true; | ||
| return createErrorBoundary$1(() => { | ||
| if (hydrated) { | ||
| hydrated = false; | ||
| throw err; | ||
| } | ||
| return fn(); | ||
| }, fallback); | ||
| } | ||
| } | ||
| return createErrorBoundary$1(fn, fallback); | ||
| } | ||
| function hydratedCreateOptimistic(fn, second, third) { | ||
| if (typeof fn !== "function" || !sharedConfig.hydrating) return createOptimistic$1(fn, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client") { | ||
| const [hydrated, setHydrated] = createSignal$1(false); | ||
| const sig = createOptimistic$1(prev => { | ||
| if (!hydrated()) return prev ?? second; | ||
| return fn(prev); | ||
| }, second, third); | ||
| setHydrated(true); | ||
| return sig; | ||
| } | ||
| if (ssrSource === "initial") { | ||
| return createOptimistic$1(prev => { | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| subFetch(fn, prev); | ||
| return prev ?? second; | ||
| }, second, third); | ||
| } | ||
| const aiResult = hydrateSignalFromAsyncIterable(createOptimistic$1, fn, second, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return createOptimistic$1(prev => { | ||
| const o = getOwner(); | ||
| if (!sharedConfig.hydrating) return fn(prev); | ||
| let initP; | ||
| if (sharedConfig.has(o.id)) initP = sharedConfig.load(o.id); | ||
| const init = initP?.v ?? initP; | ||
| return init != null ? (subFetch(fn, prev), init) : fn(prev); | ||
| }, second, third); | ||
| } | ||
| function wrapStoreFn(fn, ssrSource) { | ||
| if (ssrSource === "initial") { | ||
| return draft => { | ||
| if (!sharedConfig.hydrating) return fn(draft); | ||
| subFetch(fn, draft); | ||
| return undefined; | ||
| }; | ||
| } | ||
| return draft => { | ||
| const o = getOwner(); | ||
| if (!sharedConfig.hydrating) return fn(draft); | ||
| let initP; | ||
| if (sharedConfig.has(o.id)) initP = sharedConfig.load(o.id); | ||
| const init = initP?.v ?? initP; | ||
| return init != null ? (subFetch(fn, draft), init) : fn(draft); | ||
| }; | ||
| } | ||
| function hydratedCreateStore(first, second, third) { | ||
| if (typeof first !== "function" || !sharedConfig.hydrating) return createStore$1(first, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return createStore$1(second ?? {}, undefined, third); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(createStore$1, second ?? {}, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return createStore$1(wrapStoreFn(first, ssrSource), second, third); | ||
| } | ||
| function hydratedCreateOptimisticStore(first, second, third) { | ||
| if (typeof first !== "function" || !sharedConfig.hydrating) return createOptimisticStore$1(first, second, third); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = third?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return createOptimisticStore$1(second ?? {}, undefined, third); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(createOptimisticStore$1, second ?? {}, third); | ||
| if (aiResult !== null) return aiResult; | ||
| return createOptimisticStore$1(wrapStoreFn(first, ssrSource), second, third); | ||
| } | ||
| function hydratedCreateProjection(fn, initialValue, options) { | ||
| if (!sharedConfig.hydrating) return createProjection$1(fn, initialValue, options); | ||
| markTopLevelSnapshotScope(); | ||
| const ssrSource = options?.ssrSource; | ||
| if (ssrSource === "client" || ssrSource === "initial") { | ||
| return createProjection$1(draft => draft, initialValue, options); | ||
| } | ||
| const aiResult = hydrateStoreFromAsyncIterable(createStore$1, initialValue, options); | ||
| if (aiResult !== null) return aiResult[0]; | ||
| return createProjection$1(wrapStoreFn(fn, ssrSource), initialValue, options); | ||
| } | ||
| function enableHydration() { | ||
| _createMemo = hydratedCreateMemo; | ||
| _createSignal = hydratedCreateSignal; | ||
| _createErrorBoundary = hydratedCreateErrorBoundary; | ||
| _createOptimistic = hydratedCreateOptimistic; | ||
| _createProjection = hydratedCreateProjection; | ||
| _createStore = hydratedCreateStore; | ||
| _createOptimisticStore = hydratedCreateOptimisticStore; | ||
| _hydratingValue = sharedConfig.hydrating; | ||
| _doneValue = sharedConfig.done; | ||
| Object.defineProperty(sharedConfig, "hydrating", { | ||
| get() { | ||
| return _hydratingValue; | ||
| }, | ||
| set(v) { | ||
| const was = _hydratingValue; | ||
| _hydratingValue = v; | ||
| if (!was && v) { | ||
| _hydrationDone = false; | ||
| _doneValue = false; | ||
| _pendingBoundaries = 0; | ||
| setSnapshotCapture(true); | ||
| _snapshotRootOwner = null; | ||
| } else if (was && !v) { | ||
| if (_snapshotRootOwner) { | ||
| releaseSnapshotScope(_snapshotRootOwner); | ||
| _snapshotRootOwner = null; | ||
| } | ||
| checkHydrationComplete(); | ||
| } | ||
| }, | ||
| configurable: true, | ||
| enumerable: true | ||
| }); | ||
| Object.defineProperty(sharedConfig, "done", { | ||
| get() { | ||
| return _doneValue; | ||
| }, | ||
| set(v) { | ||
| _doneValue = v; | ||
| if (v) drainHydrationCallbacks(); | ||
| }, | ||
| configurable: true, | ||
| enumerable: true | ||
| }); | ||
| } | ||
| const createMemo = (...args) => (_createMemo || createMemo$1)(...args); | ||
| const createSignal = (...args) => (_createSignal || createSignal$1)(...args); | ||
| const createErrorBoundary = (...args) => (_createErrorBoundary || createErrorBoundary$1)(...args); | ||
| const createOptimistic = (...args) => (_createOptimistic || createOptimistic$1)(...args); | ||
| const createProjection = (...args) => (_createProjection || createProjection$1)(...args); | ||
| const createStore = (...args) => (_createStore || createStore$1)(...args); | ||
| const createOptimisticStore = (...args) => (_createOptimisticStore || createOptimisticStore$1)(...args); | ||
| function loadModuleAssets(mapping) { | ||
| const hy = globalThis._$HY; | ||
| if (!hy) return; | ||
| if (!hy.modules) hy.modules = {}; | ||
| if (!hy.loading) hy.loading = {}; | ||
| const pending = []; | ||
| for (const moduleUrl in mapping) { | ||
| if (hy.modules[moduleUrl]) continue; | ||
| const entryUrl = mapping[moduleUrl]; | ||
| if (!hy.loading[moduleUrl]) { | ||
| hy.loading[moduleUrl] = import(entryUrl).then(mod => { | ||
| hy.modules[moduleUrl] = mod; | ||
| }); | ||
| } | ||
| pending.push(hy.loading[moduleUrl]); | ||
| } | ||
| return pending.length ? Promise.all(pending).then(() => {}) : undefined; | ||
| } | ||
| function createBoundaryTrigger() { | ||
| setSnapshotCapture(false); | ||
| const [s, set] = createSignal$1(undefined, { | ||
| equals: false | ||
| }); | ||
| s(); | ||
| setSnapshotCapture(true); | ||
| return set; | ||
| } | ||
| function resumeBoundaryHydration(o, id, set) { | ||
| _pendingBoundaries--; | ||
| if (isDisposed(o)) { | ||
| checkHydrationComplete(); | ||
| return; | ||
| } | ||
| sharedConfig.gather(id); | ||
| _hydratingValue = true; | ||
| markSnapshotScope(o); | ||
| _snapshotRootOwner = o; | ||
| set(); | ||
| flush(); | ||
| _snapshotRootOwner = null; | ||
| _hydratingValue = false; | ||
| releaseSnapshotScope(o); | ||
| flush(); | ||
| checkHydrationComplete(); | ||
| } | ||
| function Loading(props) { | ||
@@ -121,2 +466,7 @@ if (!sharedConfig.hydrating) return createLoadBoundary(() => props.children, () => props.fallback); | ||
| const id = o.id; | ||
| let assetPromise; | ||
| if (sharedConfig.hydrating && sharedConfig.has(id + "_assets")) { | ||
| const mapping = sharedConfig.load(id + "_assets"); | ||
| if (mapping && typeof mapping === "object") assetPromise = loadModuleAssets(mapping); | ||
| } | ||
| if (sharedConfig.hydrating && sharedConfig.has(id)) { | ||
@@ -129,20 +479,34 @@ let ref = sharedConfig.load(id); | ||
| if (p) { | ||
| const [s, set] = createSignal$1(undefined, { | ||
| equals: false | ||
| _pendingBoundaries++; | ||
| onCleanup(() => { | ||
| if (!isDisposed(o)) return; | ||
| sharedConfig.cleanupFragment?.(id); | ||
| }); | ||
| s(); | ||
| const set = createBoundaryTrigger(); | ||
| if (p !== "$$f") { | ||
| p.then(() => { | ||
| sharedConfig.gather(id); | ||
| sharedConfig.hydrating = true; | ||
| const waitFor = assetPromise ? Promise.all([p, assetPromise]) : p; | ||
| waitFor.then(() => resumeBoundaryHydration(o, id, set), err => { | ||
| _pendingBoundaries--; | ||
| checkHydrationComplete(); | ||
| runWithOwner(o, () => { | ||
| throw err; | ||
| }); | ||
| }); | ||
| } else { | ||
| const afterAssets = () => { | ||
| _pendingBoundaries--; | ||
| set(); | ||
| flush(); | ||
| sharedConfig.hydrating = false; | ||
| }, err => runWithOwner(o, () => { | ||
| throw err; | ||
| })); | ||
| } else queueMicrotask(set); | ||
| checkHydrationComplete(); | ||
| }; | ||
| if (assetPromise) assetPromise.then(() => queueMicrotask(afterAssets));else queueMicrotask(afterAssets); | ||
| } | ||
| return props.fallback; | ||
| } | ||
| } | ||
| if (assetPromise) { | ||
| _pendingBoundaries++; | ||
| const set = createBoundaryTrigger(); | ||
| assetPromise.then(() => resumeBoundaryHydration(o, id, set)); | ||
| return undefined; | ||
| } | ||
| return createLoadBoundary(() => props.children, () => props.fallback); | ||
@@ -155,7 +519,20 @@ }); | ||
| } | ||
| function lazy(fn) { | ||
| function lazy(fn, moduleUrl) { | ||
| let comp; | ||
| let p; | ||
| const wrap = props => { | ||
| comp = createMemo$1(() => (p || (p = fn())).then(mod => mod.default)); | ||
| if (sharedConfig.hydrating && moduleUrl) { | ||
| const cached = globalThis._$HY?.modules?.[moduleUrl]; | ||
| if (!cached) { | ||
| throw new Error(`lazy() module "${moduleUrl}" was not preloaded before hydration. ` + "Ensure it is inside a Loading boundary."); | ||
| } | ||
| comp = () => cached.default; | ||
| } | ||
| if (!comp) { | ||
| p || (p = fn()); | ||
| p.then(mod => { | ||
| comp = () => mod.default; | ||
| }); | ||
| comp = createMemo$1(() => p.then(mod => mod.default)); | ||
| } | ||
| let Comp; | ||
@@ -202,6 +579,11 @@ return createMemo$1(() => (Comp = comp()) ? untrack(() => { | ||
| const fn = typeof child === "function" && child.length > 0; | ||
| return fn ? untrack(() => child(() => { | ||
| if (!untrack(condition)) throw narrowedError("Show"); | ||
| return conditionValue(); | ||
| })) : child; | ||
| return fn ? untrack(() => { | ||
| try { | ||
| return child(() => { | ||
| if (!untrack(condition)) throw narrowedError("Show"); | ||
| return conditionValue(); | ||
| }); | ||
| } finally { | ||
| } | ||
| }) : child; | ||
| } | ||
@@ -234,6 +616,11 @@ return props.fallback; | ||
| const fn = typeof child === "function" && child.length > 0; | ||
| return fn ? untrack(() => child(() => { | ||
| if (untrack(switchFunc)()?.[0] !== index) throw narrowedError("Match"); | ||
| return conditionValue(); | ||
| })) : child; | ||
| return fn ? untrack(() => { | ||
| try { | ||
| return child(() => { | ||
| if (untrack(switchFunc)()?.[0] !== index) throw narrowedError("Match"); | ||
| return conditionValue(); | ||
| }); | ||
| } finally { | ||
| } | ||
| }) : child; | ||
| }, undefined, undefined); | ||
@@ -255,2 +642,2 @@ } | ||
| export { $DEVCOMP, DEV, Errored, For, Loading, Match, Repeat, Show, Switch, children, createComponent, createContext, createMemo, createSignal, createUniqueId, enableHydration, lazy, sharedConfig, ssrHandleError, ssrRunInScope, useContext }; | ||
| export { $DEVCOMP, DEV, Errored, For, Loading, Match, Repeat, Show, Switch, children, createComponent, createContext, createMemo, createOptimistic, createOptimisticStore, createProjection, createSignal, createStore, createUniqueId, enableHydration, lazy, sharedConfig, ssrHandleError, ssrRunInScope, useContext }; |
+2
-2
| { | ||
| "name": "solid-js", | ||
| "description": "A declarative JavaScript library for building user interfaces.", | ||
| "version": "2.0.0-experimental.14", | ||
| "version": "2.0.0-experimental.15", | ||
| "author": "Ryan Carniato", | ||
@@ -82,3 +82,3 @@ "license": "MIT", | ||
| "dependencies": { | ||
| "@solidjs/signals": "^0.10.2", | ||
| "@solidjs/signals": "^0.10.8", | ||
| "csstype": "^3.1.0", | ||
@@ -85,0 +85,0 @@ "seroval": "~1.5.0", |
@@ -69,3 +69,3 @@ import type { JSX } from "../jsx.js"; | ||
| default: T; | ||
| }>): T & { | ||
| }>, moduleUrl?: string): T & { | ||
| preload: () => Promise<{ | ||
@@ -72,0 +72,0 @@ default: T; |
@@ -1,4 +0,16 @@ | ||
| import { createMemo as coreMemo, createSignal as coreSignal } from "@solidjs/signals"; | ||
| import { createErrorBoundary as coreErrorBoundary, createMemo as coreMemo, createSignal as coreSignal, createOptimistic as coreOptimistic, type ProjectionOptions, type Store, type StoreSetter } from "@solidjs/signals"; | ||
| import { JSX } from "../jsx.js"; | ||
| export { createStore, createProjection, createOptimistic, createOptimisticStore } from "@solidjs/signals"; | ||
| declare module "@solidjs/signals" { | ||
| interface MemoOptions<T> { | ||
| deferStream?: boolean; | ||
| ssrSource?: "server" | "hybrid" | "initial" | "client"; | ||
| } | ||
| interface SignalOptions<T> { | ||
| deferStream?: boolean; | ||
| ssrSource?: "server" | "hybrid" | "initial" | "client"; | ||
| } | ||
| } | ||
| export type HydrationProjectionOptions = ProjectionOptions & { | ||
| ssrSource?: "server" | "hybrid" | "initial" | "client"; | ||
| }; | ||
| export type HydrationContext = {}; | ||
@@ -13,2 +25,3 @@ type SharedConfig = { | ||
| gather?: (key: string) => void; | ||
| cleanupFragment?: (id: string) => void; | ||
| registry?: Map<string, Element>; | ||
@@ -19,5 +32,23 @@ done: boolean; | ||
| export declare const sharedConfig: SharedConfig; | ||
| /** | ||
| * Registers a callback to run once when all hydration completes | ||
| * (all boundaries hydrated or cancelled). If hydration is already | ||
| * complete (or not hydrating), fires via queueMicrotask. | ||
| */ | ||
| export declare function onHydrationEnd(callback: () => void): void; | ||
| export declare function enableHydration(): void; | ||
| export declare const createMemo: typeof coreMemo; | ||
| export declare const createSignal: typeof coreSignal; | ||
| export declare const createErrorBoundary: typeof coreErrorBoundary; | ||
| export declare const createOptimistic: typeof coreOptimistic; | ||
| export declare const createProjection: <T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, initialValue?: T, options?: HydrationProjectionOptions) => Store<T>; | ||
| type NoFn<T> = T extends Function ? never : T; | ||
| export declare const createStore: { | ||
| <T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>): [get: Store<T>, set: StoreSetter<T>]; | ||
| <T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store?: NoFn<T> | Store<NoFn<T>>, options?: HydrationProjectionOptions): [get: Store<T>, set: StoreSetter<T>]; | ||
| }; | ||
| export declare const createOptimisticStore: { | ||
| <T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>): [get: Store<T>, set: StoreSetter<T>]; | ||
| <T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store?: NoFn<T> | Store<NoFn<T>>, options?: HydrationProjectionOptions): [get: Store<T>, set: StoreSetter<T>]; | ||
| }; | ||
| /** | ||
@@ -38,1 +69,2 @@ * Tracks all resources inside a component and renders a fallback until they are all resolved | ||
| }): JSX.Element; | ||
| export {}; |
@@ -53,7 +53,11 @@ import type { JSX } from "../jsx.js"; | ||
| * Lazy load a function component asynchronously. | ||
| * On server, caches the promise and throws NotReadyError if not yet loaded. | ||
| * On server, returns a createMemo that throws NotReadyError until the module resolves, | ||
| * allowing resolveSSRNode to capture it as a fine-grained hole. The memo naturally | ||
| * scopes the owner so hydration IDs align with the client's createMemo in lazy(). | ||
| * Requires `moduleUrl` for SSR — the bundler plugin injects the module specifier | ||
| * so the server can look up client chunk URLs from the asset manifest. | ||
| */ | ||
| export declare function lazy<T extends Component<any>>(fn: () => Promise<{ | ||
| default: T; | ||
| }>): T & { | ||
| }>, moduleUrl?: string): T & { | ||
| preload: () => Promise<{ | ||
@@ -60,0 +64,0 @@ default: T; |
@@ -1,3 +0,3 @@ | ||
| export { $PROXY, $TRACK, action, createEffect, createMemo, createOptimistic, createOptimisticStore, createProjection, createReaction, createRenderEffect, createRoot, createSignal, createStore, createTrackedEffect, deep, flatten, flush, getObserver, getOwner, isEqual, isRefreshing, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, pending, reconcile, refresh, repeat, resolve, NotReadyError, runWithOwner, snapshot, untrack } from "./signals.js"; | ||
| export type { Accessor, ComputeFunction, EffectFunction, EffectOptions, Merge, NoInfer, NotWrappable, Omit, Owner, Signal, SignalOptions, Setter, Store, SolidStore, StoreNode, StoreSetter } from "./signals.js"; | ||
| export { $PROXY, $TRACK, action, createEffect, createMemo, createOptimistic, createOptimisticStore, createProjection, createReaction, createRenderEffect, createRoot, createSignal, createStore, createTrackedEffect, deep, flatten, flush, getObserver, getOwner, isEqual, isRefreshing, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, pending, reconcile, refresh, repeat, resolve, NotReadyError, runWithOwner, snapshot, createDeepProxy, untrack } from "./signals.js"; | ||
| export type { Accessor, ComputeFunction, EffectFunction, EffectOptions, Merge, NoInfer, NotWrappable, Omit, Owner, Signal, SignalOptions, Setter, Store, SolidStore, StoreNode, StoreSetter, PatchOp } from "./signals.js"; | ||
| export { $DEVCOMP, children, createContext, useContext, ssrRunInScope } from "./core.js"; | ||
@@ -4,0 +4,0 @@ export type { ChildrenReturn, Context, ContextProviderComponent, ResolvedChildren, ResolvedJSXElement } from "./core.js"; |
@@ -9,3 +9,9 @@ type SSRTemplateObject = { | ||
| count: number; | ||
| serialize: (id: string, v: Promise<any> | any, deferStream?: boolean) => void; | ||
| /** | ||
| * Serialize a value for client hydration. | ||
| * In renderToStream (async: true), accepts promises and async iterables. | ||
| * In renderToString (async: false), only synchronous values are allowed — | ||
| * passing async values will throw. | ||
| */ | ||
| serialize: (id: string, v: any, deferStream?: boolean) => void; | ||
| resolve(value: any): SSRTemplateObject; | ||
@@ -17,2 +23,17 @@ ssr(template: string[], ...values: any[]): SSRTemplateObject; | ||
| registerFragment: (v: string) => (v?: string, err?: any) => boolean; | ||
| /** Register a client-side asset URL discovered during SSR (e.g. from lazy()). */ | ||
| registerAsset?: (type: "module" | "style", url: string) => void; | ||
| /** Register a moduleUrl-to-entryUrl mapping for the current boundary. */ | ||
| registerModule?: (moduleUrl: string, entryUrl: string) => void; | ||
| /** Resolve a module's JS and CSS assets from the asset manifest. Set by dom-expressions. */ | ||
| resolveAssets?: (moduleUrl: string) => { | ||
| js: string[]; | ||
| css: string[]; | ||
| } | null; | ||
| /** Retrieve the moduleUrl-to-entryUrl map for a boundary. */ | ||
| getBoundaryModules?: (id: string) => Record<string, string> | null; | ||
| /** @internal Tracks which Loading boundary is currently rendering. Set by dom-expressions via applyAssetTracking(). */ | ||
| _currentBoundaryId?: string | null; | ||
| assets: any[]; | ||
| /** True only in renderToStream — enables async data serialization and streaming. */ | ||
| async?: boolean; | ||
@@ -19,0 +40,0 @@ noHydrate: boolean; |
@@ -12,2 +12,3 @@ export { createRoot, createOwner, runWithOwner, getOwner, onCleanup, getNextChildId, createContext, setContext, getContext, NotReadyError, NoOwnerError, ContextNotFoundError, isEqual, isWrappable, SUPPORTS_PROXY } from "@solidjs/signals"; | ||
| computed: boolean; | ||
| disposed: boolean; | ||
| } | ||
@@ -20,2 +21,4 @@ export declare function getObserver(): ServerComputation<any> | null; | ||
| export declare function createMemo<Next extends Prev, Init = Next, Prev = Next>(compute: ComputeFunction<Init | Prev, Next>, value: Init, options?: MemoOptions<Next>): Accessor<Next>; | ||
| export type PatchOp = [path: PropertyKey[]] | [path: PropertyKey[], value: any] | [path: PropertyKey[], value: any, insert: 1]; | ||
| export declare function createDeepProxy<T extends object>(target: T, patches: PatchOp[], basePath?: PropertyKey[]): T; | ||
| export declare function createEffect<Next>(compute: ComputeFunction<undefined | NoInfer<Next>, Next>, effectFn: EffectFunction<NoInfer<Next>, Next> | EffectBundle<NoInfer<Next>, Next>): void; | ||
@@ -30,5 +33,8 @@ export declare function createEffect<Next, Init = Next>(compute: ComputeFunction<Init | Next, Next>, effect: EffectFunction<Next, Next> | EffectBundle<Next, Next>, value: Init, options?: EffectOptions): void; | ||
| export declare function createOptimistic<T>(fn: ComputeFunction<T>, initialValue?: T, options?: SignalOptions<T>): Signal<T>; | ||
| export declare function createStore<T extends object>(state: T | Store<T>): [get: Store<T>, set: StoreSetter<T>]; | ||
| export declare function createStore<T extends object>(first: T | Store<T> | ((store: T) => void | T | Promise<void | T>), second?: T | Store<T>): [get: Store<T>, set: StoreSetter<T>]; | ||
| export declare const createOptimisticStore: typeof createStore; | ||
| export declare function createProjection<T extends object>(fn: (draft: T) => void, initialValue?: T): Store<T>; | ||
| export declare function createProjection<T extends object>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, initialValue?: T, options?: { | ||
| deferStream?: boolean; | ||
| ssrSource?: string; | ||
| }): Store<T>; | ||
| export declare function reconcile<T extends U, U extends object>(value: T): (state: U) => T; | ||
@@ -35,0 +41,0 @@ export declare function deep<T extends object>(store: Store<T>): Store<T>; |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
355978
27.89%9148
31.68%Updated