Files
SnowLuma/.pnpm-store/v11/files/11/03a9319020a9d345ca01d14e313432750dd6462b645266290d359c096ff39c54b859dd8890838c6bf3ab3e22663e8aa39586effc8b1be3c9f409c77cb7fbbe
T
TanTan 2a69b23b47
Dev Build / cleanup (push) Canceled after 0s
Dev Build / typecheck (push) Canceled after 0s
Dev Build / build (linux-arm64, ubuntu-24.04-arm, linux-arm64) (push) Canceled after 0s
Dev Build / build (linux-x64, ubuntu-latest, linux-x64) (push) Canceled after 0s
Dev Build / build (win-x64, windows-latest, win32-x64) (push) Canceled after 0s
Dev Build / dispatch-dev-docker (push) Canceled after 0s
docs: 仓库链接指向本镜像仓库
2026-11-13 09:27:07 +08:00

171 lines
6.4 KiB
Plaintext

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_utils_html = require("../utils/html.js");
const require_jsx_constants = require("./constants.js");
const require_jsx_dom_context = require("./dom/context.js");
const require_jsx_base = require("./base.js");
//#region src/jsx/context.ts
const globalContexts = [];
let alsProbed = false;
let asyncLocalStorage;
let fallbackStore;
let fallbackRendersInFlight = 0;
let warnedFallbackDefault = false;
const loadAsyncLocalStorage = () => {
if (alsProbed) return asyncLocalStorage;
alsProbed = true;
const global = globalThis;
let AsyncLocalStorage;
for (const probe of [() => global.process?.getBuiltinModule?.("node:async_hooks")?.AsyncLocalStorage, () => global.process?.mainModule?.require?.("node:async_hooks")?.AsyncLocalStorage]) {
try {
AsyncLocalStorage = probe();
} catch {}
if (AsyncLocalStorage) break;
}
if (AsyncLocalStorage) asyncLocalStorage = new AsyncLocalStorage();
return asyncLocalStorage;
};
const getCurrentStore = () => {
return loadAsyncLocalStorage()?.getStore() || fallbackStore;
};
const warnIfStorelessAccess = () => {
if (fallbackRendersInFlight > 0 && !warnedFallbackDefault) {
warnedFallbackDefault = true;
console.warn("hono/jsx: AsyncLocalStorage is unavailable in this runtime, so useContext() after an await in an async component falls back to the context default value during server-side rendering. To get provided values across await boundaries, use a runtime with AsyncLocalStorage (Node.js >= 20.16, Deno, Bun, or Cloudflare Workers with the nodejs_compat flag).");
}
};
const getContextValuesIn = (store, context) => {
if (!store) {
warnIfStorelessAccess();
return context.values;
}
let values = store.get(context);
if (!values) {
values = [context.values[0]];
store.set(context, values);
}
return values;
};
const readContextValueIn = (store, context) => {
if (!store) {
warnIfStorelessAccess();
return context.values.at(-1);
}
const values = store.get(context);
return values?.length ? values.at(-1) : context.values[0];
};
const captureContextValues = (store) => (store ? globalContexts.filter((c) => store.has(c)) : globalContexts).map((c) => [c, readContextValueIn(store, c)]);
const resumeWithContextValues = (callback, store, contexts) => runWithRenderContext(() => {
const currentStore = getCurrentStore();
const valuesPerContext = contexts.map(([context, value]) => {
const values = getContextValuesIn(currentStore, context);
values.push(value);
return values;
});
const popContextValues = () => {
valuesPerContext.forEach((values) => {
values.pop();
});
};
try {
const result = callback();
if (result instanceof Promise) return result.finally(popContextValues);
popContextValues();
return result;
} catch (e) {
popContextValues();
throw e;
}
}, store);
/**
* Establish the request-scoped context store for a render.
*
* `resumeStore` continues a suspended subtree in the same store on the fallback
* path (ignored when `AsyncLocalStorage` is available, where isolation is
* automatic).
*
* Without `AsyncLocalStorage` a render can't be followed across `await`, so the
* store lives in `fallbackStore` only during synchronous work (mirroring
* React's request storage). Reading context after `await` then finds no store
* and falls back to the default value — never another request's value.
*/
const runWithRenderContext = (callback, resumeStore) => {
if (getCurrentStore()) return callback();
const store = resumeStore ?? /* @__PURE__ */ new WeakMap();
const storage = loadAsyncLocalStorage();
if (storage) return storage.run(store, callback);
fallbackStore = store;
let result;
try {
result = callback();
} finally {
fallbackStore = void 0;
}
if (!warnedFallbackDefault && result instanceof Promise) {
fallbackRendersInFlight++;
result = result.finally(() => {
fallbackRendersInFlight--;
});
}
return result;
};
/**
* Capture the current render store and return a resumer that re-establishes it
* around a deferred continuation (e.g. a re-render after a suspended promise
* settles). Shared by every suspension point so none reimplements it.
*/
const captureRenderContext = () => {
const store = getCurrentStore();
const contexts = captureContextValues(store);
return (callback) => resumeWithContextValues(callback, store, contexts);
};
/**
* Create a context whose value can be provided with `<Context.Provider>` and
* read with {@link useContext}.
*
* Server-side renders are isolated per request, so a provided value never leaks
* into a concurrent request — even across `await` in an async component, when
* `AsyncLocalStorage` is available (Node.js >= 20.16, Deno, Bun, Cloudflare
* Workers with `nodejs_compat`). Without it, reading context after `await`
* returns the default value; synchronous components and `use()`-based
* suspension are unaffected.
*/
const createContext = (defaultValue) => {
const values = [defaultValue];
const context = ((props) => {
const contextValues = getContextValuesIn(getCurrentStore(), context);
contextValues.push(props.value);
let rendered;
try {
rendered = typeof props.children === "string" ? require_jsx_base.renderChildren([props.children]) : require_jsx_base.isUntrustedObject(props.children) ? require_jsx_base.renderUntrustedObject(props.children) : props.children ? (Array.isArray(props.children) ? new require_jsx_base.JSXFragmentNode("", {}, props.children) : props.children).toString() : require_utils_html.raw("");
} catch (e) {
contextValues.pop();
throw e;
}
if (rendered instanceof Promise) return rendered.finally(() => contextValues.pop()).then((resString) => require_utils_html.raw(resString, resString.callbacks));
else {
contextValues.pop();
return require_utils_html.raw(rendered);
}
});
context.values = values;
context.Provider = context;
context[require_jsx_constants.DOM_RENDERER] = require_jsx_dom_context.createContextProviderFunction(values);
globalContexts.push(context);
return context;
};
/**
* Read the current value of a context created with {@link createContext}.
*
* Safe to call from async components after `await`. See {@link createContext}
* for the per-runtime isolation guarantees.
*/
const useContext = (context) => {
return readContextValueIn(getCurrentStore(), context);
};
//#endregion
exports.captureRenderContext = captureRenderContext;
exports.createContext = createContext;
exports.globalContexts = globalContexts;
exports.runWithRenderContext = runWithRenderContext;
exports.useContext = useContext;