hono
Version:
Web framework built on Web Standards
189 lines (188 loc) • 6.28 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var context_exports = {};
__export(context_exports, {
captureRenderContext: () => captureRenderContext,
createContext: () => createContext,
globalContexts: () => globalContexts,
runWithRenderContext: () => runWithRenderContext,
useContext: () => useContext
});
module.exports = __toCommonJS(context_exports);
var import_html = require("../helper/html");
var import_base = require("./base");
var import_constants = require("./constants");
var import_context = require("./dom/context");
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 [
// Node.js >= 20.16, Deno, Bun, Cloudflare Workers (nodejs_compat). Property
// access only, so bundlers don't statically resolve `node:async_hooks`.
() => global.process?.getBuiltinModule?.("node:async_hooks")?.AsyncLocalStorage,
// Node.js < 20.16 has no `process.getBuiltinModule`, but a CJS entrypoint
// exposes the main module's `require` here.
() => 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);
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;
};
const captureRenderContext = () => {
const store = getCurrentStore();
const contexts = captureContextValues(store);
return (callback) => resumeWithContextValues(callback, store, contexts);
};
const createContext = (defaultValue) => {
const values = [defaultValue];
const context = ((props) => {
const contextValues = getContextValuesIn(getCurrentStore(), context);
contextValues.push(props.value);
let string;
try {
string = props.children ? (Array.isArray(props.children) ? new import_base.JSXFragmentNode("", {}, props.children) : props.children).toString() : "";
} catch (e) {
contextValues.pop();
throw e;
}
if (string instanceof Promise) {
return string.finally(() => contextValues.pop()).then((resString) => (0, import_html.raw)(resString, resString.callbacks));
} else {
contextValues.pop();
return (0, import_html.raw)(string);
}
});
context.values = values;
context.Provider = context;
context[import_constants.DOM_RENDERER] = (0, import_context.createContextProviderFunction)(values);
globalContexts.push(context);
return context;
};
const useContext = (context) => {
return readContextValueIn(getCurrentStore(), context);
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
captureRenderContext,
createContext,
globalContexts,
runWithRenderContext,
useContext
});