@tanstack/start-client-core
Version:
Modern and scalable routing for React applications
129 lines (128 loc) • 4.03 kB
JavaScript
import { hydrateIdAttribute, hydrateWhenAttribute } from "./constants.js";
//#region src/hydration/runtime.ts
var hydrateIdSelector = `[${hydrateIdAttribute}]`;
var gateRegistry = /* @__PURE__ */ new Map();
var resolvedGateIds = /* @__PURE__ */ new Set();
var fallbackHtmlByGateId = /* @__PURE__ */ new Map();
function createResolvedGate(id, when) {
return {
id,
when,
promise: Promise.resolve(),
resolve: () => {},
resolved: true,
consumers: 0,
resolveListeners: /* @__PURE__ */ new Set()
};
}
function getOrCreateGate(id, when) {
const existing = gateRegistry.get(id);
if (existing?.when === when) {
existing.consumers++;
return existing;
}
let resolvePromise;
const gate = {
id,
promise: new Promise((resolve) => {
resolvePromise = resolve;
}),
resolved: false,
consumers: 1,
when,
resolveListeners: /* @__PURE__ */ new Set(),
resolve: () => {
if (gate.resolved) return;
gate.resolved = true;
resolvePromise();
gate.resolveListeners.forEach((listener) => listener());
gate.resolveListeners.clear();
}
};
gateRegistry.set(id, gate);
if (when !== "never" && resolvedGateIds.has(id)) {
resolvedGateIds.delete(id);
gate.resolve();
}
return gate;
}
function releaseGate(gate) {
resolvedGateIds.delete(gate.id);
gate.consumers--;
if (gate.consumers > 0) return;
if (gateRegistry.get(gate.id) === gate) {
gateRegistry.delete(gate.id);
fallbackHtmlByGateId.delete(gate.id);
gate.resolveListeners.clear();
}
}
function onGateResolve(gate, listener) {
if (gate.resolved) {
listener();
return () => {};
}
gate.resolveListeners.add(listener);
return () => {
gate.resolveListeners.delete(listener);
};
}
function runHydrationStrategyCleanup(cleanup) {
if (typeof cleanup === "function") return cleanup;
}
function waitForHydrationPrefetchStrategy(strategy, options) {
if (options.signal.aborted) return Promise.resolve("abort");
return new Promise((resolve) => {
const state = { disposed: false };
const cleanupStrategyRef = { current: void 0 };
let cleanupHydrate = () => {};
const finish = (reason) => {
if (state.disposed) return;
state.disposed = true;
options.signal.removeEventListener("abort", onAbort);
cleanupHydrate();
runHydrationStrategyCleanup(cleanupStrategyRef.current)?.();
resolve(reason);
};
const onAbort = () => finish("abort");
options.signal.addEventListener("abort", onAbort, { once: true });
cleanupHydrate = options.onHydrate(() => finish("hydrate"));
const cleanupStrategy = strategy._s?.({
element: options.element,
prefetch: () => finish("prefetch")
});
cleanupStrategyRef.current = cleanupStrategy;
if (state.disposed) runHydrationStrategyCleanup(cleanupStrategy)?.();
});
}
function getMarkerGate(marker) {
const id = marker.getAttribute(hydrateIdAttribute);
return id ? gateRegistry.get(id) : void 0;
}
function resolveHydrationMarker(marker) {
const id = marker.getAttribute(hydrateIdAttribute);
const when = marker.getAttribute(hydrateWhenAttribute);
if (!id || !when || when === "never") return;
const gate = gateRegistry.get(id);
if (gate) {
if (gate.when !== "never") gate.resolve();
return;
}
resolvedGateIds.add(id);
}
function clearResolvedGateIdsInMarker(marker) {
const ownId = marker.getAttribute(hydrateIdAttribute);
if (ownId) resolvedGateIds.delete(ownId);
marker.querySelectorAll(hydrateIdSelector).forEach((childMarker) => {
const childId = childMarker.getAttribute(hydrateIdAttribute);
if (childId) resolvedGateIds.delete(childId);
});
}
function saveFallbackHtml(id, element) {
if (!fallbackHtmlByGateId.has(id)) fallbackHtmlByGateId.set(id, element.innerHTML);
}
function getFallbackHtml(id) {
return fallbackHtmlByGateId.get(id);
}
//#endregion
export { clearResolvedGateIdsInMarker, createResolvedGate, getFallbackHtml, getMarkerGate, getOrCreateGate, onGateResolve, releaseGate, resolveHydrationMarker, runHydrationStrategyCleanup, saveFallbackHtml, waitForHydrationPrefetchStrategy };
//# sourceMappingURL=runtime.js.map