elysia 2.0.0-beta.21 → 2.0.0-beta.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +1 -0
  2. package/dist/adapter/bun/index.d.ts +6 -8
  3. package/dist/adapter/bun/index.js +6 -8
  4. package/dist/adapter/bun/index.mjs +7 -8
  5. package/dist/adapter/constants.mjs +1 -0
  6. package/dist/adapter/default-headers.mjs +1 -0
  7. package/dist/adapter/index.mjs +1 -0
  8. package/dist/adapter/origin.mjs +1 -0
  9. package/dist/adapter/response-ownership.mjs +1 -0
  10. package/dist/adapter/skip-clone.mjs +1 -0
  11. package/dist/adapter/types.mjs +1 -0
  12. package/dist/adapter/utils.d.ts +5 -8
  13. package/dist/adapter/utils.js +24 -18
  14. package/dist/adapter/utils.mjs +25 -18
  15. package/dist/adapter/web-standard/handler.mjs +2 -1
  16. package/dist/adapter/web-standard/index.mjs +1 -0
  17. package/dist/adapter/web-standard/utils.mjs +1 -0
  18. package/dist/base.d.ts +118 -69
  19. package/dist/base.js +213 -193
  20. package/dist/base.mjs +220 -199
  21. package/dist/compile/aot-capture.js +2 -2
  22. package/dist/compile/aot-capture.mjs +4 -3
  23. package/dist/compile/aot-emit.js +7 -8
  24. package/dist/compile/aot-emit.mjs +8 -8
  25. package/dist/compile/aot-reconstruct.mjs +3 -2
  26. package/dist/compile/aot.d.ts +3 -3
  27. package/dist/compile/aot.js +5 -5
  28. package/dist/compile/aot.mjs +6 -5
  29. package/dist/compile/handler/descriptor.d.ts +2 -5
  30. package/dist/compile/handler/descriptor.js +12 -17
  31. package/dist/compile/handler/descriptor.mjs +16 -21
  32. package/dist/compile/handler/frozen-validator.d.ts +2 -2
  33. package/dist/compile/handler/frozen-validator.js +3 -3
  34. package/dist/compile/handler/frozen-validator.mjs +4 -3
  35. package/dist/compile/handler/index.d.ts +3 -1
  36. package/dist/compile/handler/index.js +77 -118
  37. package/dist/compile/handler/index.mjs +83 -125
  38. package/dist/compile/handler/jit.d.ts +12 -12
  39. package/dist/compile/handler/jit.js +60 -43
  40. package/dist/compile/handler/jit.mjs +63 -47
  41. package/dist/compile/handler/params.d.ts +5 -1
  42. package/dist/compile/handler/params.js +14 -5
  43. package/dist/compile/handler/params.mjs +16 -7
  44. package/dist/compile/handler/reconstruct.d.ts +2 -2
  45. package/dist/compile/handler/reconstruct.js +2 -2
  46. package/dist/compile/handler/reconstruct.mjs +3 -2
  47. package/dist/compile/handler/static-clone-resolver.mjs +1 -0
  48. package/dist/compile/handler/utils.d.ts +13 -7
  49. package/dist/compile/handler/utils.js +75 -52
  50. package/dist/compile/handler/utils.mjs +77 -54
  51. package/dist/compile/jit-probe.mjs +1 -0
  52. package/dist/compile/lexer.js +4 -4
  53. package/dist/compile/lexer.mjs +5 -4
  54. package/dist/compile/utils.d.ts +2 -1
  55. package/dist/compile/utils.js +8 -3
  56. package/dist/compile/utils.mjs +8 -3
  57. package/dist/compiled.mjs +1 -0
  58. package/dist/constants.mjs +1 -0
  59. package/dist/context.d.ts +1 -1
  60. package/dist/context.js +1 -0
  61. package/dist/context.mjs +3 -1
  62. package/dist/cookie/config.d.ts +2 -2
  63. package/dist/cookie/config.js +21 -26
  64. package/dist/cookie/config.mjs +22 -26
  65. package/dist/cookie/cookie.mjs +1 -0
  66. package/dist/cookie/crypto.mjs +1 -0
  67. package/dist/cookie/error.mjs +1 -0
  68. package/dist/cookie/lib.mjs +1 -0
  69. package/dist/cookie/serialize.mjs +1 -0
  70. package/dist/cookie/types.mjs +1 -0
  71. package/dist/cookie/utils.d.ts +1 -1
  72. package/dist/cookie/utils.js +64 -45
  73. package/dist/cookie/utils.mjs +66 -46
  74. package/dist/error.d.ts +10 -6
  75. package/dist/error.js +22 -6
  76. package/dist/error.mjs +25 -9
  77. package/dist/generation.mjs +1 -0
  78. package/dist/handler/error.d.ts +12 -15
  79. package/dist/handler/error.js +43 -40
  80. package/dist/handler/error.mjs +45 -41
  81. package/dist/handler/fetch.js +59 -21
  82. package/dist/handler/fetch.mjs +61 -22
  83. package/dist/handler/utils.d.ts +16 -3
  84. package/dist/handler/utils.js +14 -13
  85. package/dist/handler/utils.mjs +16 -15
  86. package/dist/index.d.ts +9 -9
  87. package/dist/index.js +1 -0
  88. package/dist/index.mjs +3 -2
  89. package/dist/memory.mjs +1 -0
  90. package/dist/package.js +1 -1
  91. package/dist/package.mjs +2 -1
  92. package/dist/parse-query.js +76 -76
  93. package/dist/parse-query.mjs +77 -76
  94. package/dist/plugin/aot/bun.mjs +1 -0
  95. package/dist/plugin/aot/core.js +7 -4
  96. package/dist/plugin/aot/core.mjs +8 -5
  97. package/dist/plugin/aot/esbuild.mjs +1 -0
  98. package/dist/plugin/aot/rspack-loader.mjs +1 -0
  99. package/dist/plugin/aot/rspack.mjs +1 -0
  100. package/dist/plugin/aot/treeshake.mjs +1 -0
  101. package/dist/plugin/aot/unplugin.mjs +4 -3
  102. package/dist/plugin/aot/vite.mjs +1 -0
  103. package/dist/plugin/aot/worker.mjs +1 -0
  104. package/dist/plugin/auto-head.mjs +1 -0
  105. package/dist/plugin/trace.mjs +1 -0
  106. package/dist/plugin/websocket.mjs +1 -0
  107. package/dist/route-table.mjs +1 -0
  108. package/dist/schema-snapshot.mjs +1 -0
  109. package/dist/sucrose.d.ts +2 -2
  110. package/dist/sucrose.js +11 -11
  111. package/dist/sucrose.mjs +12 -11
  112. package/dist/trace.js +8 -10
  113. package/dist/trace.mjs +10 -11
  114. package/dist/type/bridge-live.d.ts +1 -1
  115. package/dist/type/bridge-live.mjs +1 -0
  116. package/dist/type/bridge.d.ts +1 -1
  117. package/dist/type/bridge.mjs +1 -0
  118. package/dist/type/coerce-plan.mjs +1 -0
  119. package/dist/type/coerce.d.ts +1 -1
  120. package/dist/type/coerce.mjs +1 -0
  121. package/dist/type/compat.mjs +1 -0
  122. package/dist/type/constants.d.ts +1 -1
  123. package/dist/type/constants.mjs +1 -0
  124. package/dist/type/elysia/accelerate.mjs +1 -0
  125. package/dist/type/elysia/array-buffer.d.ts +3 -2
  126. package/dist/type/elysia/array-buffer.js +5 -5
  127. package/dist/type/elysia/array-buffer.mjs +6 -5
  128. package/dist/type/elysia/array-string.mjs +1 -0
  129. package/dist/type/elysia/array.mjs +1 -0
  130. package/dist/type/elysia/boolean-string.mjs +1 -0
  131. package/dist/type/elysia/boolean.mjs +1 -0
  132. package/dist/type/elysia/cookie.mjs +1 -0
  133. package/dist/type/elysia/date.mjs +1 -0
  134. package/dist/type/elysia/file-type.mjs +1 -0
  135. package/dist/type/elysia/file.mjs +1 -0
  136. package/dist/type/elysia/files.mjs +1 -0
  137. package/dist/type/elysia/form.mjs +1 -0
  138. package/dist/type/elysia/integer-string.mjs +1 -0
  139. package/dist/type/elysia/integer.mjs +1 -0
  140. package/dist/type/elysia/intersect.mjs +1 -0
  141. package/dist/type/elysia/json-string.mjs +1 -0
  142. package/dist/type/elysia/keep-config.js +8 -8
  143. package/dist/type/elysia/keep-config.mjs +9 -8
  144. package/dist/type/elysia/maybe-empty.mjs +1 -0
  145. package/dist/type/elysia/no-validate.mjs +1 -0
  146. package/dist/type/elysia/nullable.mjs +1 -0
  147. package/dist/type/elysia/number.mjs +1 -0
  148. package/dist/type/elysia/numeric-enum.d.ts +4 -2
  149. package/dist/type/elysia/numeric-enum.mjs +1 -0
  150. package/dist/type/elysia/numeric.mjs +1 -0
  151. package/dist/type/elysia/object-string.mjs +1 -0
  152. package/dist/type/elysia/object.mjs +1 -0
  153. package/dist/type/elysia/optional.mjs +1 -0
  154. package/dist/type/elysia/problem.mjs +1 -0
  155. package/dist/type/elysia/string.mjs +1 -0
  156. package/dist/type/elysia/uint8-array.d.ts +2 -1
  157. package/dist/type/elysia/uint8-array.js +2 -2
  158. package/dist/type/elysia/uint8-array.mjs +3 -2
  159. package/dist/type/elysia/union-enum.mjs +1 -0
  160. package/dist/type/elysia/union.mjs +1 -0
  161. package/dist/type/elysia/utils.js +3 -3
  162. package/dist/type/elysia/utils.mjs +4 -3
  163. package/dist/type/exports.mjs +1 -0
  164. package/dist/type/index.mjs +2 -1
  165. package/dist/type/shared.mjs +1 -0
  166. package/dist/type/sync-require.mjs +1 -0
  167. package/dist/type/typebox-system-lite.mjs +1 -0
  168. package/dist/type/typebox-system-require.mjs +1 -0
  169. package/dist/type/typebox-type-live.mjs +1 -0
  170. package/dist/type/typebox-value-live.mjs +1 -0
  171. package/dist/type/typebox-value-ops.mjs +1 -0
  172. package/dist/type/typebox-value.mjs +1 -0
  173. package/dist/type/types.d.ts +1 -1
  174. package/dist/type/types.mjs +1 -0
  175. package/dist/type/utils.mjs +1 -0
  176. package/dist/type/validator/clean-safe.mjs +1 -0
  177. package/dist/type/validator/custom-error.js +41 -33
  178. package/dist/type/validator/custom-error.mjs +42 -33
  179. package/dist/type/validator/default-precompute.d.ts +2 -2
  180. package/dist/type/validator/default-precompute.js +10 -11
  181. package/dist/type/validator/default-precompute.mjs +13 -13
  182. package/dist/type/validator/exact-mirror.mjs +1 -0
  183. package/dist/type/validator/frozen-check.js +7 -7
  184. package/dist/type/validator/frozen-check.mjs +8 -7
  185. package/dist/type/validator/index.d.ts +2 -2
  186. package/dist/type/validator/index.js +4 -8
  187. package/dist/type/validator/index.mjs +5 -8
  188. package/dist/type/validator/string-codec-aot.d.ts +1 -1
  189. package/dist/type/validator/string-codec-aot.mjs +1 -0
  190. package/dist/type/validator/validator-cache.js +18 -18
  191. package/dist/type/validator/validator-cache.mjs +19 -18
  192. package/dist/types.d.ts +105 -69
  193. package/dist/types.mjs +1 -0
  194. package/dist/universal/constants.mjs +1 -0
  195. package/dist/universal/file.mjs +1 -0
  196. package/dist/universal/index.mjs +1 -0
  197. package/dist/universal/is-production.mjs +1 -0
  198. package/dist/universal/server.mjs +1 -0
  199. package/dist/utils.d.ts +49 -31
  200. package/dist/utils.js +221 -109
  201. package/dist/utils.mjs +215 -106
  202. package/dist/validator/index.d.ts +3 -3
  203. package/dist/validator/index.js +4 -4
  204. package/dist/validator/index.mjs +5 -4
  205. package/dist/validator/route.d.ts +2 -2
  206. package/dist/validator/route.mjs +1 -0
  207. package/dist/ws/context.js +1 -1
  208. package/dist/ws/context.mjs +2 -1
  209. package/dist/ws/index.mjs +1 -0
  210. package/dist/ws/parser.mjs +1 -0
  211. package/dist/ws/route.js +34 -25
  212. package/dist/ws/route.mjs +40 -30
  213. package/dist/ws/types.d.ts +2 -3
  214. package/dist/ws/types.mjs +1 -0
  215. package/package.json +2 -2
@@ -7,9 +7,15 @@ import { TailMode } from "./utils.js";
7
7
 
8
8
  //#region src/compile/handler/jit.d.ts
9
9
  /**
10
- * @internal test hook: receives each route's emitted source. A sync-first
11
- * route's async tail is a helper beside it, so `toString()` of the compiled
12
- * handler does not show the whole pipeline
10
+ * @internal one factory per emitted source, each route calls it for its own
11
+ * closure. JSC stops sharing code between identical `new Function` sources
12
+ * once its source cache churns, so without this every route links a copy
13
+ */
14
+ declare const factoryCache: Map<string, Function>;
15
+ declare const FACTORY_CACHE_LIMIT = 256;
16
+ /**
17
+ * @internal test hook: receives each route's full emitted source, including
18
+ * the async tail helper that `toString()` of the handler does not show
13
19
  */
14
20
  declare let onEmit: ((code: string) => void) | undefined;
15
21
  declare const setOnEmit: (fn: typeof onEmit) => void;
@@ -27,19 +33,13 @@ interface CompileHandlerJitOptions {
27
33
  isHandleFunction: boolean;
28
34
  isStaticResponse: boolean;
29
35
  isPromiseHandler: boolean;
30
- /**
31
- * Non-Error classes a returned value is rethrown for, see
32
- * `returnedErrorClasses`
33
- */
36
+ /** Non-Error classes a returned value is rethrown for (`returnedErrorClasses`) */
34
37
  errorClasses?: Function[];
35
- /**
36
- * Per-route descriptor + compile artifacts, computed by `describeRoute`.
37
- * The JIT no longer re-derives these facts; it names its emissions off them.
38
- */
38
+ /** Per-route descriptor + compile artifacts from `describeRoute` */
39
39
  state: RouteCompileState;
40
40
  /** `routeShape`, recorded with the captured code */
41
41
  shape?: number;
42
42
  }
43
43
  declare function compileHandlerJit(options: CompileHandlerJitOptions, tailPass?: TailMode): CompiledHandler;
44
44
  //#endregion
45
- export { CompileHandlerJitOptions, compileHandlerJit, createInlineHandler, setAsyncTail, setCaptureHeaderShorthand, setOnEmit };
45
+ export { CompileHandlerJitOptions, FACTORY_CACHE_LIMIT, compileHandlerJit, createInlineHandler, factoryCache, setAsyncTail, setCaptureHeaderShorthand, setOnEmit };
@@ -17,20 +17,25 @@ const require_compile_jit_probe = require('../jit-probe.js');
17
17
 
18
18
  //#region src/compile/handler/jit.ts
19
19
  const awaitValue = (value, arm = "") => arm ? `await (_av=(${value}),${arm},_av)` : `await ${value}`;
20
+ /**
21
+ * @internal one factory per emitted source, each route calls it for its own
22
+ * closure. JSC stops sharing code between identical `new Function` sources
23
+ * once its source cache churns, so without this every route links a copy
24
+ */
25
+ const factoryCache = /* @__PURE__ */ new Map();
26
+ const FACTORY_CACHE_LIMIT = 256;
20
27
  let captureHeaderShorthand;
21
28
  /**
22
- * @internal test hook: receives each route's emitted source. A sync-first
23
- * route's async tail is a helper beside it, so `toString()` of the compiled
24
- * handler does not show the whole pipeline
29
+ * @internal test hook: receives each route's full emitted source, including
30
+ * the async tail helper that `toString()` of the handler does not show
25
31
  */
26
32
  let onEmit;
27
33
  const setOnEmit = (fn) => {
28
34
  onEmit = fn;
29
35
  };
30
36
  /**
31
- * @internal test hook: `false` compiles sync-first routes on the `async`
32
- * lane instead, the reference the async tail is differentially tested
33
- * against. `undefined` restores the default (see `tail` below)
37
+ * @internal test hook: `false` compiles sync-first routes on the plain
38
+ * `async` lane (the differential reference), `undefined` restores the default
34
39
  */
35
40
  let asyncTailOn;
36
41
  const setAsyncTail = (on) => {
@@ -161,9 +166,22 @@ const createInlineHandler = (map, h) => ((c) => {
161
166
  if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(require_handler_utils.forwardError(v), c.request, true));
162
167
  return map(r, c.request, true);
163
168
  });
169
+ const createInlineSetHandler = (map, h) => ((c) => {
170
+ const r = h(c);
171
+ if (r instanceof Error) throw r;
172
+ if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(require_handler_utils.forwardError(v), c.set, c.request, true));
173
+ return map(r, c.set, c.request, true);
174
+ });
175
+ const createInlineDefaultHeaderHandler = (map, h) => ((c) => {
176
+ require_adapter_utils.materializeSetHeaders(c.set);
177
+ const r = h(c);
178
+ if (r instanceof Error) throw r;
179
+ if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(require_handler_utils.forwardError(v), c.set, c.request, true));
180
+ return map(r, c.set, c.request, true);
181
+ });
164
182
  function compileHandlerJit(options, tailPass) {
165
183
  const { method, path, handler, root, errorRoot, hook, adapter, isHandleFunction, isStaticResponse, isPromiseHandler, errorClasses, state, shape } = options;
166
- const { vali, inference, cookieConfig, beforeHandlePrefix, traceHandlers, tracePhases, hasAnyPhase, traceHandleOn, descriptor: { async: isAsync, tail: tailRoute, responseMode, hasBody, bodyValiIsAsync, headersValiIsAsync, paramsValiIsAsync, queryValiIsAsync, cookieValiIsAsync: cookieValidIsAsync, responseValiAsync, hasCookieSign, syncCookieSign, asyncCookieSign, lazyCookieVerify, hasErrorHook, hasAfterResponse, hasBeforeHandle, hasAfterHandle, hasMapResponse, hasResponseValidator, hasTrace, traceCount, hasLifecycleHook, syncErrorHook, syncAfterResponse } } = state;
184
+ const { vali, inference, cookieConfig, beforeHandlePrefix, traceHandlers, tracePhases, hasAnyPhase, traceHandleOn, descriptor: { async: isAsync, tail: tailRoute, responseMode, hasBody, bodyValiIsAsync, headersValiIsAsync, paramsValiIsAsync, queryValiIsAsync, cookieValiIsAsync, responseValiAsync, hasCookieSign, syncCookieSign, asyncCookieSign, lazyCookieVerify, hasErrorHook, hasAfterResponse, hasBeforeHandle, hasAfterHandle, hasMapResponse, hasResponseValidator, hasTrace, traceCount, hasLifecycleHook, syncErrorHook, syncAfterResponse } } = state;
167
185
  const hasStaticAfterResponse = !!hook?.afterResponse?.length;
168
186
  const hasDeriveDispose = !!hook?.["~deriveEntries"]?.length;
169
187
  const hasDynamicAfterResponse = !!inference.afterResponse || hasDeriveDispose;
@@ -177,7 +195,7 @@ function compileHandlerJit(options, tailPass) {
177
195
  } : isAsync;
178
196
  const plain = (code) => require_compile_handler_utils.tailPlain(asyncMode, code);
179
197
  const seenKeys = new Set(["rt", "fre"]);
180
- const paramValues = [errorRoot, require_handler_utils.finalizeRouteError];
198
+ const paramValues = [errorRoot, require_handler_utils.finalizeRouteErrorOf(hook)];
181
199
  const aliasKeys = [];
182
200
  function link(v, key) {
183
201
  if (!seenKeys.has(key)) {
@@ -193,8 +211,8 @@ function compileHandlerJit(options, tailPass) {
193
211
  const abortPeek = "c['~sig']?.aborted";
194
212
  const arm = abortOn ? "_as??=(c['~sig']??=c.request.signal)" : "";
195
213
  let abortSchedule = "";
196
- let discard = "";
197
- const abortCheck = () => abortOn ? plain(abortSchedule || discard ? `if(${abortPeek}){${discard}${abortSchedule}return emp.clone()}\n` : `if(${abortPeek})return emp.clone()\n`) : "";
214
+ let abortDiscard = "";
215
+ const abortCheck = () => abortOn ? plain(abortSchedule || abortDiscard ? `if(${abortPeek}){${abortDiscard}${abortSchedule}return emp.clone()}\n` : `if(${abortPeek})return emp.clone()\n`) : "";
198
216
  const abortChainGuard = () => abortOn ? abortPeek : void 0;
199
217
  const abortCatch = abortOn ? `if((${arm}).aborted)return emp.clone()\n` : "";
200
218
  const phaseOn = (phase) => hasTrace && (tracePhases === null || tracePhases.has(phase));
@@ -331,7 +349,7 @@ function compileHandlerJit(options, tailPass) {
331
349
  code += `c.cookie=bcj(c.set,_ck,cc,1)\n`;
332
350
  } else {
333
351
  let deferDecode = false;
334
- if (!hasCookieSign && !cookieValidIsAsync) if (!vali?.cookie) {
352
+ if (!hasCookieSign && !cookieValiIsAsync) if (!vali?.cookie) {
335
353
  link(require_cookie_utils.parseCookieRawDeferred, "pcrd");
336
354
  code += `let _ck=pcrd(${cookieHeaderExpr},cc)\n`;
337
355
  deferDecode = true;
@@ -339,7 +357,7 @@ function compileHandlerJit(options, tailPass) {
339
357
  link(require_cookie_utils.parseCookieRawSync, "pcrs");
340
358
  code += `let _ck=pcrs(${cookieHeaderExpr},cc)\n`;
341
359
  }
342
- else if (syncCookieSign && !cookieValidIsAsync) {
360
+ else if (syncCookieSign && !cookieValiIsAsync) {
343
361
  link(require_cookie_utils.parseCookieRawSigned, "pcrsg");
344
362
  code += `let _ck=pcrsg(${cookieHeaderExpr},cc)\n`;
345
363
  } else {
@@ -349,8 +367,8 @@ function compileHandlerJit(options, tailPass) {
349
367
  if (vali?.cookie) {
350
368
  link(vali, "va");
351
369
  const cookieIsOptional = !!(hook?.cookie)?.["~optional"];
352
- const value = `va.cookie.From(_ck,${fromArgs("cookie", !!cookieValidIsAsync)})`;
353
- const validateExpr = `_ck=${cookieValidIsAsync ? awaitValue(value, arm) : value}\n`;
370
+ const value = `va.cookie.From(_ck,${fromArgs("cookie", cookieValiIsAsync)})`;
371
+ const validateExpr = `_ck=${cookieValiIsAsync ? awaitValue(value, arm) : value}\n`;
354
372
  if (cookieIsOptional) code += `if(Object.keys(_ck).length){${validateExpr}}\n`;
355
373
  else code += validateExpr;
356
374
  }
@@ -388,8 +406,9 @@ function compileHandlerJit(options, tailPass) {
388
406
  abortSchedule = hasDeriveDispose ? syncAfterResponse ? catchSchedule : schedule : "";
389
407
  const freThenSchedule = (arg) => catchSchedule ? `if(c._arf)return fre(rt,c,${arg})\n${deriveDisposeOnly ? `if(c['~dispose'])` : ""}c._arf=true\nconst _fr=fre(rt,c,${arg})\nreturn typeof _fr?.then==='function'?_fr.then((_v)=>{${catchSchedule}return _v\n}):(${catchSchedule.trim()},_fr)\n` : `return fre(rt,c,${arg})\n`;
390
408
  const mapThenSchedule = (s, onReject) => `if(typeof _m?.then==='function')return Promise.resolve(_m).then((_v)=>{\n${s}return _v\n},${onReject})\n` + s + `return _m\n`;
391
- const signPrefix = syncCookieSign ? `scv(c.set.cookie,cc)\n` : asyncCookieSign ? `_sg=scv(c.set.cookie,cc)\nif(_sg){${arm ? `${arm}\n` : ""}await _sg}\n` : "";
409
+ const signPrefix = syncCookieSign ? `scv(c.set.cookie,cc,c.set)\n` : asyncCookieSign ? `_sg=scv(c.set.cookie,cc,c.set)\nif(_sg){${arm ? `${arm}\n` : ""}await _sg}\n` : "";
392
410
  if (syncCookieSign || asyncCookieSign) link(require_cookie_utils.signCookieValues, "scv");
411
+ const streamSign = signPrefix ? `if(typeof _r?.next==='function')c.set['~sign']=_sgn\n` : "";
393
412
  let factoryHelpers = "";
394
413
  let tailCatch = -1;
395
414
  if (hasBeforeHandle || hasAfterHandle || hasMapResponse || hasAfterResponse || hasResponseValidator || hasCookieSign || hasTrace) {
@@ -443,11 +462,11 @@ function compileHandlerJit(options, tailPass) {
443
462
  } else if (isHandleFunction && require_compile_handler_utils.asyncTail(asyncMode)) code += require_compile_handler_utils.tailStage(require_compile_handler_utils.asyncTail(asyncMode), hasBeforeHandle ? "_r===undefined" : void 0) + callHandler() + teeBlock + "}\n";
444
463
  else if (hasBeforeHandle) code += plain(`if(_r===undefined){\n${callHandler()}${teeBlock}}\n`);
445
464
  else code += plain(callHandler() + teeBlock);
446
- if (teeBlock) discard = "_sv?.return()\n";
465
+ if (teeBlock) abortDiscard = "_sv?.return()\n";
447
466
  code += abortCheck();
448
467
  if (syncAfterResponse) {
449
468
  if (!errorClasses) link(require_handler_utils.forwardError, "fe");
450
- factoryHelpers += syncScheduleDecl + `function _fin(c,_r){\n` + rethrow("_r") + "if(_r&&(_r[Symbol.iterator]||_r[Symbol.asyncIterator])&&typeof _r.next==='function'){\nconst _s=tee(_r,2)\nreturn _fin2(c,_s[0],_s[1],_s[0])\n}\nif(_r instanceof ReadableStream){const _o=obs(_r)\nif(_o)return _fin2(c,_o[0],_o[1],_o[2])}\nreturn _fin2(c,_r)\n}\nfunction _fin2(c,_r,_stl,_sv){try{\nc.responseValue=_r\n" + signPrefix + `const _m=${mapValue("_r")}\n` + mapThenSchedule(syncScheduleDecl ? `_scf(c,_stl)\n` : scheduleAfterResponse, `(_e)=>{_sv?.return()\n${freThenSchedule("_e")}}`) + `}catch(_e){_sv?.return();throw _e}}\n`;
469
+ factoryHelpers += syncScheduleDecl + `function _fin(c,_r){\n` + rethrow("_r") + "if(_r&&(_r[Symbol.iterator]||_r[Symbol.asyncIterator])&&typeof _r.next==='function'){\nconst _s=tee(_r,2)\nreturn _fin2(c,_s[0],_s[1],_s[0])\n}\nif(_r instanceof ReadableStream){const _o=obs(_r)\nif(_o)return _fin2(c,_o[0],_o[1],_o[2])}\nreturn _fin2(c,_r)\n}\nfunction _fin2(c,_r,_stl,_sv){try{\nc.responseValue=_r\n" + signPrefix + streamSign + `const _m=${mapValue("_r")}\n` + mapThenSchedule(syncScheduleDecl ? `_scf(c,_stl)\n` : scheduleAfterResponse, `(_e)=>{_sv?.return()\n${freThenSchedule("_e")}}`) + `}catch(_e){_sv?.return();throw _e}}\n`;
451
470
  code += `if(typeof _r?.then==='function')return Promise.resolve(_r).then(${fwd}).then((_v)=>_fin(c,_v)).catch((_e)=>{${freThenSchedule("_e")}})\nreturn _fin(c,_r)\n`;
452
471
  } else {
453
472
  code += plain(rethrow("_r"));
@@ -477,17 +496,24 @@ function compileHandlerJit(options, tailPass) {
477
496
  if (hasMapResponse) code += abortCheck();
478
497
  }
479
498
  if (hasResponseValidator) {
480
- link(vali, "va");
481
499
  link(require_error.ElysiaStatus, "es");
500
+ link(require_constants.StatusMap, "sm");
501
+ let pick = "";
502
+ let i = 0;
503
+ for (const [status, v] of vali.response) {
504
+ link(status, `vs${i}`);
505
+ link(v, `vr${i}`);
506
+ pick += `_st==vs${i}?vr${i}:`;
507
+ i++;
508
+ }
509
+ pick += "undefined";
482
510
  const encodeStatus = responseValiAsync ? `(_vr.mayReturnPromise?_vr.From(_r.response,'response',true):_vr.EncodeFrom(_r.response,'response'))` : `_vr.EncodeFrom(_r.response,'response')`;
483
511
  const encodeBody = responseValiAsync ? `(_vr.mayReturnPromise?_vr.From(_r,'response',true):_vr.EncodeFrom(_r,'response'))` : `_vr.EncodeFrom(_r,'response')`;
484
- code += plain(`if(_r instanceof es){
485
- const _vr=va.response[_r.status]
486
- if(_vr)_r.response=${responseValiAsync ? awaitValue(encodeStatus, arm) : encodeStatus}\n}else if(!(_r instanceof Response)&&!(_r instanceof ReadableStream)&&typeof _r?.next!=='function'){\nconst _vr=va.response[c.set.status??200]\nif(_vr)_r=${responseValiAsync ? awaitValue(encodeBody, arm) : encodeBody}\n}\n`);
512
+ code += plain(`if(_r instanceof es){\nconst _st=_r.status,_vr=${pick}\nif(_vr)_r.response=${responseValiAsync ? awaitValue(encodeStatus, arm) : encodeStatus}\n}else if(!(_r instanceof Response)&&!(_r instanceof ReadableStream)&&typeof _r?.next!=='function'){\nconst _sr=c.set.status??200,_st=typeof _sr==='string'?(sm[_sr]??_sr):_sr,_vr=${pick}\nif(_vr)_r=${responseValiAsync ? awaitValue(encodeBody, arm) : encodeBody}\n}\n`);
487
513
  code += abortCheck();
488
514
  }
489
515
  const deferSchedule = !!schedule;
490
- code += plain(signPrefix);
516
+ code += plain(signPrefix + streamSign);
491
517
  const finalMap = mapValue("_r");
492
518
  const onMapReject = syncErrorHook ? `(_e)=>_ce(_e,c)` : dedupSchedule ? `(_e)=>{${freThenSchedule("_e")}}` : `(_e)=>fre(rt,c,_e)`;
493
519
  if (tail) code += `let _m\n${stageSite(finalMap, "_m")}` + (deferSchedule ? schedule : "") + `return _m\n`;
@@ -558,7 +584,7 @@ if(_vr)_r.response=${responseValiAsync ? awaitValue(encodeStatus, arm) : encodeS
558
584
  }
559
585
  if (syncCookieSign || asyncCookieSign) {
560
586
  code = code.replaceAll("fre(rt,c,", "_sfre(rt,c,");
561
- factoryHelpers = factoryHelpers.replaceAll("fre(rt,c,", "_sfre(rt,c,") + `function _sgn(s){return scv(s.cookie,cc)}\nfunction _sfre(rt,c,e){return fre(rt,c,e,_sgn)}\n`;
587
+ factoryHelpers = factoryHelpers.replaceAll("fre(rt,c,", "_sfre(rt,c,") + `function _sgn(s){return scv(s.cookie,cc,s)}\nfunction _sfre(rt,c,e){return fre(rt,c,e,_sgn)}\n`;
562
588
  }
563
589
  if (factoryHelpers) code = `(function(){\n${factoryHelpers}return ${code}})()`;
564
590
  const alias = aliasKeys.join(",");
@@ -574,33 +600,24 @@ if(_vr)_r.response=${responseValiAsync ? awaitValue(encodeStatus, arm) : encodeS
574
600
  const isGeneratorHandler = isHandleFunction && handler.constructor.name.endsWith("GeneratorFunction");
575
601
  if (!hasTrace && isHandleFunction && !isGeneratorHandler && !inlineUnsafe) {
576
602
  if (alias === "rc" || !isAsync && !syncErrorHook && alias === "rc,fe") return createInlineHandler(responseCompact, handler);
577
- else if (alias === "rm" || alias === "msh,rm" || !isAsync && !syncErrorHook && (alias === "rm,fe" || alias === "msh,rm,fe")) {
578
- const rmap = responseMap;
579
- const h = handler;
580
- let inlineHandler;
581
- if (responseMode === "set-with-default-headers" && inference.set) inlineHandler = ((c) => {
582
- require_adapter_utils.materializeSetHeaders(c.set);
583
- const r = h(c);
584
- if (r instanceof Error) throw r;
585
- if (typeof r?.then === "function") return Promise.resolve(r).then((v) => rmap(require_handler_utils.forwardError(v), c.set, c.request, true));
586
- return rmap(r, c.set, c.request, true);
587
- });
588
- else inlineHandler = ((c) => {
589
- const r = h(c);
590
- if (r instanceof Error) throw r;
591
- if (typeof r?.then === "function") return Promise.resolve(r).then((v) => rmap(require_handler_utils.forwardError(v), c.set, c.request, true));
592
- return rmap(r, c.set, c.request, true);
593
- });
594
- return inlineHandler;
595
- }
603
+ else if (alias === "rm" || alias === "msh,rm" || !isAsync && !syncErrorHook && (alias === "rm,fe" || alias === "msh,rm,fe")) return responseMode === "set-with-default-headers" && inference.set ? createInlineDefaultHeaderHandler(responseMap, handler) : createInlineSetHandler(responseMap, handler);
596
604
  }
597
605
  require_compile_jit_probe.JITProbe.record("handler:new-function");
598
- return new Function("h", fullAlias, `return ${code}`)(handler, ...paramValues);
606
+ const key = fullAlias + "\n" + code;
607
+ let factory = factoryCache.get(key);
608
+ if (!factory) {
609
+ if (factoryCache.size >= 256) require_utils.evictOldestHalf(factoryCache);
610
+ factory = new Function("h", fullAlias, `return ${code}`);
611
+ factoryCache.set(key, factory);
612
+ }
613
+ return factory(handler, ...paramValues);
599
614
  }
600
615
 
601
616
  //#endregion
617
+ exports.FACTORY_CACHE_LIMIT = FACTORY_CACHE_LIMIT;
602
618
  exports.compileHandlerJit = compileHandlerJit;
603
619
  exports.createInlineHandler = createInlineHandler;
620
+ exports.factoryCache = factoryCache;
604
621
  exports.setAsyncTail = setAsyncTail;
605
622
  exports.setCaptureHeaderShorthand = setCaptureHeaderShorthand;
606
623
  exports.setOnEmit = setOnEmit;
@@ -1,6 +1,7 @@
1
+ // @bun
1
2
  import { hasHeaderShorthand, isBun } from "../../universal/constants.mjs";
2
- import { isDynamicRegex, traceEventIndex } from "../../constants.mjs";
3
- import { requestId } from "../../utils.mjs";
3
+ import { StatusMap, isDynamicRegex, traceEventIndex } from "../../constants.mjs";
4
+ import { evictOldestHalf, requestId } from "../../utils.mjs";
4
5
  import { isProduction } from "../../universal/is-production.mjs";
5
6
  import { ELYSIA_TYPES } from "../../type/constants.mjs";
6
7
  import { ElysiaStatus, ParseError, ValidationError } from "../../error.mjs";
@@ -9,27 +10,32 @@ import { parseQueryFromURL } from "../../parse-query.mjs";
9
10
  import { Capture } from "../aot.mjs";
10
11
  import { resolvedTraceOf, traceCapabilityRequired } from "../../generation.mjs";
11
12
  import { buildCookieJar, parseCookieRaw, parseCookieRawDeferred, parseCookieRawLazy, parseCookieRawSigned, parseCookieRawSync, signCookieValues } from "../../cookie/utils.mjs";
12
- import { drainDisposables, emptyResponse, finalizeRouteError, forwardError, forwardErrorOf } from "../../handler/utils.mjs";
13
+ import { drainDisposables, emptyResponse, finalizeRouteErrorOf, forwardError, forwardErrorOf } from "../../handler/utils.mjs";
13
14
  import { fallbackResponse } from "../../handler/error.mjs";
14
15
  import { armEntryAbort, asyncTail, awaitGuard, awaitSite, cloneResponse, cloneStaticValue, getQueryParseChannels, hasRequestBody, mapAfterResponse, mapBeforeHandle, mapChainHook, mapError, mapTransform, runBeforeHandlePrefix, runBeforeHandlePrefixAsync, tailPlain, tailStage } from "./utils.mjs";
15
16
  import { JITProbe } from "../jit-probe.mjs";
16
17
 
17
18
  //#region src/compile/handler/jit.ts
18
19
  const awaitValue = (value, arm = "") => arm ? `await (_av=(${value}),${arm},_av)` : `await ${value}`;
20
+ /**
21
+ * @internal one factory per emitted source, each route calls it for its own
22
+ * closure. JSC stops sharing code between identical `new Function` sources
23
+ * once its source cache churns, so without this every route links a copy
24
+ */
25
+ const factoryCache = /* @__PURE__ */ new Map();
26
+ const FACTORY_CACHE_LIMIT = 256;
19
27
  let captureHeaderShorthand;
20
28
  /**
21
- * @internal test hook: receives each route's emitted source. A sync-first
22
- * route's async tail is a helper beside it, so `toString()` of the compiled
23
- * handler does not show the whole pipeline
29
+ * @internal test hook: receives each route's full emitted source, including
30
+ * the async tail helper that `toString()` of the handler does not show
24
31
  */
25
32
  let onEmit;
26
33
  const setOnEmit = (fn) => {
27
34
  onEmit = fn;
28
35
  };
29
36
  /**
30
- * @internal test hook: `false` compiles sync-first routes on the `async`
31
- * lane instead, the reference the async tail is differentially tested
32
- * against. `undefined` restores the default (see `tail` below)
37
+ * @internal test hook: `false` compiles sync-first routes on the plain
38
+ * `async` lane (the differential reference), `undefined` restores the default
33
39
  */
34
40
  let asyncTailOn;
35
41
  const setAsyncTail = (on) => {
@@ -160,9 +166,22 @@ const createInlineHandler = (map, h) => ((c) => {
160
166
  if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(forwardError(v), c.request, true));
161
167
  return map(r, c.request, true);
162
168
  });
169
+ const createInlineSetHandler = (map, h) => ((c) => {
170
+ const r = h(c);
171
+ if (r instanceof Error) throw r;
172
+ if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(forwardError(v), c.set, c.request, true));
173
+ return map(r, c.set, c.request, true);
174
+ });
175
+ const createInlineDefaultHeaderHandler = (map, h) => ((c) => {
176
+ materializeSetHeaders(c.set);
177
+ const r = h(c);
178
+ if (r instanceof Error) throw r;
179
+ if (typeof r?.then === "function") return Promise.resolve(r).then((v) => map(forwardError(v), c.set, c.request, true));
180
+ return map(r, c.set, c.request, true);
181
+ });
163
182
  function compileHandlerJit(options, tailPass) {
164
183
  const { method, path, handler, root, errorRoot, hook, adapter, isHandleFunction, isStaticResponse, isPromiseHandler, errorClasses, state, shape } = options;
165
- const { vali, inference, cookieConfig, beforeHandlePrefix, traceHandlers, tracePhases, hasAnyPhase, traceHandleOn, descriptor: { async: isAsync, tail: tailRoute, responseMode, hasBody, bodyValiIsAsync, headersValiIsAsync, paramsValiIsAsync, queryValiIsAsync, cookieValiIsAsync: cookieValidIsAsync, responseValiAsync, hasCookieSign, syncCookieSign, asyncCookieSign, lazyCookieVerify, hasErrorHook, hasAfterResponse, hasBeforeHandle, hasAfterHandle, hasMapResponse, hasResponseValidator, hasTrace, traceCount, hasLifecycleHook, syncErrorHook, syncAfterResponse } } = state;
184
+ const { vali, inference, cookieConfig, beforeHandlePrefix, traceHandlers, tracePhases, hasAnyPhase, traceHandleOn, descriptor: { async: isAsync, tail: tailRoute, responseMode, hasBody, bodyValiIsAsync, headersValiIsAsync, paramsValiIsAsync, queryValiIsAsync, cookieValiIsAsync, responseValiAsync, hasCookieSign, syncCookieSign, asyncCookieSign, lazyCookieVerify, hasErrorHook, hasAfterResponse, hasBeforeHandle, hasAfterHandle, hasMapResponse, hasResponseValidator, hasTrace, traceCount, hasLifecycleHook, syncErrorHook, syncAfterResponse } } = state;
166
185
  const hasStaticAfterResponse = !!hook?.afterResponse?.length;
167
186
  const hasDeriveDispose = !!hook?.["~deriveEntries"]?.length;
168
187
  const hasDynamicAfterResponse = !!inference.afterResponse || hasDeriveDispose;
@@ -176,7 +195,7 @@ function compileHandlerJit(options, tailPass) {
176
195
  } : isAsync;
177
196
  const plain = (code) => tailPlain(asyncMode, code);
178
197
  const seenKeys = new Set(["rt", "fre"]);
179
- const paramValues = [errorRoot, finalizeRouteError];
198
+ const paramValues = [errorRoot, finalizeRouteErrorOf(hook)];
180
199
  const aliasKeys = [];
181
200
  function link(v, key) {
182
201
  if (!seenKeys.has(key)) {
@@ -192,8 +211,8 @@ function compileHandlerJit(options, tailPass) {
192
211
  const abortPeek = "c['~sig']?.aborted";
193
212
  const arm = abortOn ? "_as??=(c['~sig']??=c.request.signal)" : "";
194
213
  let abortSchedule = "";
195
- let discard = "";
196
- const abortCheck = () => abortOn ? plain(abortSchedule || discard ? `if(${abortPeek}){${discard}${abortSchedule}return emp.clone()}\n` : `if(${abortPeek})return emp.clone()\n`) : "";
214
+ let abortDiscard = "";
215
+ const abortCheck = () => abortOn ? plain(abortSchedule || abortDiscard ? `if(${abortPeek}){${abortDiscard}${abortSchedule}return emp.clone()}\n` : `if(${abortPeek})return emp.clone()\n`) : "";
197
216
  const abortChainGuard = () => abortOn ? abortPeek : void 0;
198
217
  const abortCatch = abortOn ? `if((${arm}).aborted)return emp.clone()\n` : "";
199
218
  const phaseOn = (phase) => hasTrace && (tracePhases === null || tracePhases.has(phase));
@@ -330,7 +349,7 @@ function compileHandlerJit(options, tailPass) {
330
349
  code += `c.cookie=bcj(c.set,_ck,cc,1)\n`;
331
350
  } else {
332
351
  let deferDecode = false;
333
- if (!hasCookieSign && !cookieValidIsAsync) if (!vali?.cookie) {
352
+ if (!hasCookieSign && !cookieValiIsAsync) if (!vali?.cookie) {
334
353
  link(parseCookieRawDeferred, "pcrd");
335
354
  code += `let _ck=pcrd(${cookieHeaderExpr},cc)\n`;
336
355
  deferDecode = true;
@@ -338,7 +357,7 @@ function compileHandlerJit(options, tailPass) {
338
357
  link(parseCookieRawSync, "pcrs");
339
358
  code += `let _ck=pcrs(${cookieHeaderExpr},cc)\n`;
340
359
  }
341
- else if (syncCookieSign && !cookieValidIsAsync) {
360
+ else if (syncCookieSign && !cookieValiIsAsync) {
342
361
  link(parseCookieRawSigned, "pcrsg");
343
362
  code += `let _ck=pcrsg(${cookieHeaderExpr},cc)\n`;
344
363
  } else {
@@ -348,8 +367,8 @@ function compileHandlerJit(options, tailPass) {
348
367
  if (vali?.cookie) {
349
368
  link(vali, "va");
350
369
  const cookieIsOptional = !!(hook?.cookie)?.["~optional"];
351
- const value = `va.cookie.From(_ck,${fromArgs("cookie", !!cookieValidIsAsync)})`;
352
- const validateExpr = `_ck=${cookieValidIsAsync ? awaitValue(value, arm) : value}\n`;
370
+ const value = `va.cookie.From(_ck,${fromArgs("cookie", cookieValiIsAsync)})`;
371
+ const validateExpr = `_ck=${cookieValiIsAsync ? awaitValue(value, arm) : value}\n`;
353
372
  if (cookieIsOptional) code += `if(Object.keys(_ck).length){${validateExpr}}\n`;
354
373
  else code += validateExpr;
355
374
  }
@@ -387,8 +406,9 @@ function compileHandlerJit(options, tailPass) {
387
406
  abortSchedule = hasDeriveDispose ? syncAfterResponse ? catchSchedule : schedule : "";
388
407
  const freThenSchedule = (arg) => catchSchedule ? `if(c._arf)return fre(rt,c,${arg})\n${deriveDisposeOnly ? `if(c['~dispose'])` : ""}c._arf=true\nconst _fr=fre(rt,c,${arg})\nreturn typeof _fr?.then==='function'?_fr.then((_v)=>{${catchSchedule}return _v\n}):(${catchSchedule.trim()},_fr)\n` : `return fre(rt,c,${arg})\n`;
389
408
  const mapThenSchedule = (s, onReject) => `if(typeof _m?.then==='function')return Promise.resolve(_m).then((_v)=>{\n${s}return _v\n},${onReject})\n` + s + `return _m\n`;
390
- const signPrefix = syncCookieSign ? `scv(c.set.cookie,cc)\n` : asyncCookieSign ? `_sg=scv(c.set.cookie,cc)\nif(_sg){${arm ? `${arm}\n` : ""}await _sg}\n` : "";
409
+ const signPrefix = syncCookieSign ? `scv(c.set.cookie,cc,c.set)\n` : asyncCookieSign ? `_sg=scv(c.set.cookie,cc,c.set)\nif(_sg){${arm ? `${arm}\n` : ""}await _sg}\n` : "";
391
410
  if (syncCookieSign || asyncCookieSign) link(signCookieValues, "scv");
411
+ const streamSign = signPrefix ? `if(typeof _r?.next==='function')c.set['~sign']=_sgn\n` : "";
392
412
  let factoryHelpers = "";
393
413
  let tailCatch = -1;
394
414
  if (hasBeforeHandle || hasAfterHandle || hasMapResponse || hasAfterResponse || hasResponseValidator || hasCookieSign || hasTrace) {
@@ -442,11 +462,11 @@ function compileHandlerJit(options, tailPass) {
442
462
  } else if (isHandleFunction && asyncTail(asyncMode)) code += tailStage(asyncTail(asyncMode), hasBeforeHandle ? "_r===undefined" : void 0) + callHandler() + teeBlock + "}\n";
443
463
  else if (hasBeforeHandle) code += plain(`if(_r===undefined){\n${callHandler()}${teeBlock}}\n`);
444
464
  else code += plain(callHandler() + teeBlock);
445
- if (teeBlock) discard = "_sv?.return()\n";
465
+ if (teeBlock) abortDiscard = "_sv?.return()\n";
446
466
  code += abortCheck();
447
467
  if (syncAfterResponse) {
448
468
  if (!errorClasses) link(forwardError, "fe");
449
- factoryHelpers += syncScheduleDecl + `function _fin(c,_r){\n` + rethrow("_r") + "if(_r&&(_r[Symbol.iterator]||_r[Symbol.asyncIterator])&&typeof _r.next==='function'){\nconst _s=tee(_r,2)\nreturn _fin2(c,_s[0],_s[1],_s[0])\n}\nif(_r instanceof ReadableStream){const _o=obs(_r)\nif(_o)return _fin2(c,_o[0],_o[1],_o[2])}\nreturn _fin2(c,_r)\n}\nfunction _fin2(c,_r,_stl,_sv){try{\nc.responseValue=_r\n" + signPrefix + `const _m=${mapValue("_r")}\n` + mapThenSchedule(syncScheduleDecl ? `_scf(c,_stl)\n` : scheduleAfterResponse, `(_e)=>{_sv?.return()\n${freThenSchedule("_e")}}`) + `}catch(_e){_sv?.return();throw _e}}\n`;
469
+ factoryHelpers += syncScheduleDecl + `function _fin(c,_r){\n` + rethrow("_r") + "if(_r&&(_r[Symbol.iterator]||_r[Symbol.asyncIterator])&&typeof _r.next==='function'){\nconst _s=tee(_r,2)\nreturn _fin2(c,_s[0],_s[1],_s[0])\n}\nif(_r instanceof ReadableStream){const _o=obs(_r)\nif(_o)return _fin2(c,_o[0],_o[1],_o[2])}\nreturn _fin2(c,_r)\n}\nfunction _fin2(c,_r,_stl,_sv){try{\nc.responseValue=_r\n" + signPrefix + streamSign + `const _m=${mapValue("_r")}\n` + mapThenSchedule(syncScheduleDecl ? `_scf(c,_stl)\n` : scheduleAfterResponse, `(_e)=>{_sv?.return()\n${freThenSchedule("_e")}}`) + `}catch(_e){_sv?.return();throw _e}}\n`;
450
470
  code += `if(typeof _r?.then==='function')return Promise.resolve(_r).then(${fwd}).then((_v)=>_fin(c,_v)).catch((_e)=>{${freThenSchedule("_e")}})\nreturn _fin(c,_r)\n`;
451
471
  } else {
452
472
  code += plain(rethrow("_r"));
@@ -476,17 +496,24 @@ function compileHandlerJit(options, tailPass) {
476
496
  if (hasMapResponse) code += abortCheck();
477
497
  }
478
498
  if (hasResponseValidator) {
479
- link(vali, "va");
480
499
  link(ElysiaStatus, "es");
500
+ link(StatusMap, "sm");
501
+ let pick = "";
502
+ let i = 0;
503
+ for (const [status, v] of vali.response) {
504
+ link(status, `vs${i}`);
505
+ link(v, `vr${i}`);
506
+ pick += `_st==vs${i}?vr${i}:`;
507
+ i++;
508
+ }
509
+ pick += "undefined";
481
510
  const encodeStatus = responseValiAsync ? `(_vr.mayReturnPromise?_vr.From(_r.response,'response',true):_vr.EncodeFrom(_r.response,'response'))` : `_vr.EncodeFrom(_r.response,'response')`;
482
511
  const encodeBody = responseValiAsync ? `(_vr.mayReturnPromise?_vr.From(_r,'response',true):_vr.EncodeFrom(_r,'response'))` : `_vr.EncodeFrom(_r,'response')`;
483
- code += plain(`if(_r instanceof es){
484
- const _vr=va.response[_r.status]
485
- if(_vr)_r.response=${responseValiAsync ? awaitValue(encodeStatus, arm) : encodeStatus}\n}else if(!(_r instanceof Response)&&!(_r instanceof ReadableStream)&&typeof _r?.next!=='function'){\nconst _vr=va.response[c.set.status??200]\nif(_vr)_r=${responseValiAsync ? awaitValue(encodeBody, arm) : encodeBody}\n}\n`);
512
+ code += plain(`if(_r instanceof es){\nconst _st=_r.status,_vr=${pick}\nif(_vr)_r.response=${responseValiAsync ? awaitValue(encodeStatus, arm) : encodeStatus}\n}else if(!(_r instanceof Response)&&!(_r instanceof ReadableStream)&&typeof _r?.next!=='function'){\nconst _sr=c.set.status??200,_st=typeof _sr==='string'?(sm[_sr]??_sr):_sr,_vr=${pick}\nif(_vr)_r=${responseValiAsync ? awaitValue(encodeBody, arm) : encodeBody}\n}\n`);
486
513
  code += abortCheck();
487
514
  }
488
515
  const deferSchedule = !!schedule;
489
- code += plain(signPrefix);
516
+ code += plain(signPrefix + streamSign);
490
517
  const finalMap = mapValue("_r");
491
518
  const onMapReject = syncErrorHook ? `(_e)=>_ce(_e,c)` : dedupSchedule ? `(_e)=>{${freThenSchedule("_e")}}` : `(_e)=>fre(rt,c,_e)`;
492
519
  if (tail) code += `let _m\n${stageSite(finalMap, "_m")}` + (deferSchedule ? schedule : "") + `return _m\n`;
@@ -557,7 +584,7 @@ if(_vr)_r.response=${responseValiAsync ? awaitValue(encodeStatus, arm) : encodeS
557
584
  }
558
585
  if (syncCookieSign || asyncCookieSign) {
559
586
  code = code.replaceAll("fre(rt,c,", "_sfre(rt,c,");
560
- factoryHelpers = factoryHelpers.replaceAll("fre(rt,c,", "_sfre(rt,c,") + `function _sgn(s){return scv(s.cookie,cc)}\nfunction _sfre(rt,c,e){return fre(rt,c,e,_sgn)}\n`;
587
+ factoryHelpers = factoryHelpers.replaceAll("fre(rt,c,", "_sfre(rt,c,") + `function _sgn(s){return scv(s.cookie,cc,s)}\nfunction _sfre(rt,c,e){return fre(rt,c,e,_sgn)}\n`;
561
588
  }
562
589
  if (factoryHelpers) code = `(function(){\n${factoryHelpers}return ${code}})()`;
563
590
  const alias = aliasKeys.join(",");
@@ -573,29 +600,18 @@ if(_vr)_r.response=${responseValiAsync ? awaitValue(encodeStatus, arm) : encodeS
573
600
  const isGeneratorHandler = isHandleFunction && handler.constructor.name.endsWith("GeneratorFunction");
574
601
  if (!hasTrace && isHandleFunction && !isGeneratorHandler && !inlineUnsafe) {
575
602
  if (alias === "rc" || !isAsync && !syncErrorHook && alias === "rc,fe") return createInlineHandler(responseCompact, handler);
576
- else if (alias === "rm" || alias === "msh,rm" || !isAsync && !syncErrorHook && (alias === "rm,fe" || alias === "msh,rm,fe")) {
577
- const rmap = responseMap;
578
- const h = handler;
579
- let inlineHandler;
580
- if (responseMode === "set-with-default-headers" && inference.set) inlineHandler = ((c) => {
581
- materializeSetHeaders(c.set);
582
- const r = h(c);
583
- if (r instanceof Error) throw r;
584
- if (typeof r?.then === "function") return Promise.resolve(r).then((v) => rmap(forwardError(v), c.set, c.request, true));
585
- return rmap(r, c.set, c.request, true);
586
- });
587
- else inlineHandler = ((c) => {
588
- const r = h(c);
589
- if (r instanceof Error) throw r;
590
- if (typeof r?.then === "function") return Promise.resolve(r).then((v) => rmap(forwardError(v), c.set, c.request, true));
591
- return rmap(r, c.set, c.request, true);
592
- });
593
- return inlineHandler;
594
- }
603
+ else if (alias === "rm" || alias === "msh,rm" || !isAsync && !syncErrorHook && (alias === "rm,fe" || alias === "msh,rm,fe")) return responseMode === "set-with-default-headers" && inference.set ? createInlineDefaultHeaderHandler(responseMap, handler) : createInlineSetHandler(responseMap, handler);
595
604
  }
596
605
  JITProbe.record("handler:new-function");
597
- return new Function("h", fullAlias, `return ${code}`)(handler, ...paramValues);
606
+ const key = fullAlias + "\n" + code;
607
+ let factory = factoryCache.get(key);
608
+ if (!factory) {
609
+ if (factoryCache.size >= 256) evictOldestHalf(factoryCache);
610
+ factory = new Function("h", fullAlias, `return ${code}`);
611
+ factoryCache.set(key, factory);
612
+ }
613
+ return factory(handler, ...paramValues);
598
614
  }
599
615
 
600
616
  //#endregion
601
- export { compileHandlerJit, createInlineHandler, setAsyncTail, setCaptureHeaderShorthand, setOnEmit };
617
+ export { FACTORY_CACHE_LIMIT, compileHandlerJit, createInlineHandler, factoryCache, setAsyncTail, setCaptureHeaderShorthand, setOnEmit };
@@ -20,6 +20,10 @@ interface HandlerParamContext {
20
20
  cookieConfig: unknown;
21
21
  tracers: unknown;
22
22
  }
23
+ /**
24
+ * `vs<i>` / `vr<i>`: status and validator of the route's i-th declared response
25
+ */
26
+ declare const isResponseParam: (name: string) => boolean;
23
27
  declare function resolveHandlerParams(names: string[], c: HandlerParamContext): unknown[];
24
28
  //#endregion
25
- export { resolveHandlerParams };
29
+ export { isResponseParam, resolveHandlerParams };
@@ -1,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_constants = require('../../constants.js');
2
3
  const require_utils = require('../../utils.js');
3
4
  const require_error = require('../../error.js');
4
5
  const require_adapter_utils = require('../../adapter/utils.js');
@@ -28,6 +29,7 @@ const handlerParams = () => _handlerParams ??= {
28
29
  pq: () => require_parse_query.parseQueryFromURL,
29
30
  pe: () => require_error.ParseError,
30
31
  es: () => require_error.ElysiaStatus,
32
+ sm: () => require_constants.StatusMap,
31
33
  rdc: () => require_compile_handler_utils.replaceDeriveContext,
32
34
  dsp: () => require_handler_utils.registerDeriveDisposable,
33
35
  dds: () => require_handler_utils.drainDisposables,
@@ -49,10 +51,10 @@ const handlerParams = () => _handlerParams ??= {
49
51
  va: (c) => c.vali,
50
52
  fe: () => require_handler_utils.forwardError,
51
53
  ie: (c) => {
52
- const classes = require_handler_utils.returnedErrorClasses(c.hook, c.root);
54
+ const classes = require_handler_utils.returnedErrorClasses(c.hook);
53
55
  return classes ? require_handler_utils.forwardErrorOf(classes) : require_handler_utils.forwardError;
54
56
  },
55
- fre: () => require_handler_utils.finalizeRouteError,
57
+ fre: (c) => require_handler_utils.finalizeRouteErrorOf(c.hook),
56
58
  fbr: () => require_handler_error.fallbackResponse,
57
59
  aet: () => require_handler_error.adoptErrorType,
58
60
  rt: (c) => c.root,
@@ -66,18 +68,25 @@ const handlerParams = () => _handlerParams ??= {
66
68
  tr: (c) => c.tracers,
67
69
  cc: (c) => c.cookieConfig
68
70
  };
71
+ /**
72
+ * `vs<i>` / `vr<i>`: status and validator of the route's i-th declared response
73
+ */
74
+ const isResponseParam = (name) => /^v[rs]\d+$/.test(name);
69
75
  function resolveHandlerParams(names, c) {
70
76
  const length = names.length;
71
77
  if (!length) return [];
72
78
  const out = new Array(length);
73
79
  const params = handlerParams();
74
80
  for (let i = 0; i < length; i++) {
75
- const resolve = params[names[i]];
76
- if (!resolve) throw new Error(`[elysia-aot]: Fail to reconstruct build, missing "${names[i]}" param`);
77
- out[i] = resolve(c);
81
+ const name = names[i];
82
+ const entry = isResponseParam(name) && [...c.vali?.response ?? []][+name.slice(2)];
83
+ const resolve = params[name];
84
+ if (!entry && !resolve) throw new Error(`[elysia-aot]: Fail to reconstruct build, missing "${name}" param`);
85
+ out[i] = entry ? entry[name[1] === "s" ? 0 : 1] : resolve(c);
78
86
  }
79
87
  return out;
80
88
  }
81
89
 
82
90
  //#endregion
91
+ exports.isResponseParam = isResponseParam;
83
92
  exports.resolveHandlerParams = resolveHandlerParams;
@@ -1,9 +1,11 @@
1
+ // @bun
2
+ import { StatusMap } from "../../constants.mjs";
1
3
  import { requestId } from "../../utils.mjs";
2
4
  import { ElysiaStatus, ParseError, ValidationError } from "../../error.mjs";
3
5
  import { materializeSetHeaders, normalizeContentType, observeStream, tee } from "../../adapter/utils.mjs";
4
6
  import { parseQueryFromURL } from "../../parse-query.mjs";
5
7
  import { buildCookieJar, parseCookieRaw, parseCookieRawDeferred, parseCookieRawLazy, parseCookieRawSigned, parseCookieRawSync, signCookieValues } from "../../cookie/utils.mjs";
6
- import { drainDisposables, emptyResponse, finalizeRouteError, forwardError, forwardErrorOf, registerDeriveDisposable, returnedErrorClasses } from "../../handler/utils.mjs";
8
+ import { drainDisposables, emptyResponse, finalizeRouteErrorOf, forwardError, forwardErrorOf, registerDeriveDisposable, returnedErrorClasses } from "../../handler/utils.mjs";
7
9
  import { adoptErrorType, fallbackResponse } from "../../handler/error.mjs";
8
10
  import { armEntryAbort, cloneResponse, getQueryParseChannels, hasRequestBody, replaceDeriveContext } from "./utils.mjs";
9
11
  import { staticCloneResolver } from "./static-clone-resolver.mjs";
@@ -27,6 +29,7 @@ const handlerParams = () => _handlerParams ??= {
27
29
  pq: () => parseQueryFromURL,
28
30
  pe: () => ParseError,
29
31
  es: () => ElysiaStatus,
32
+ sm: () => StatusMap,
30
33
  rdc: () => replaceDeriveContext,
31
34
  dsp: () => registerDeriveDisposable,
32
35
  dds: () => drainDisposables,
@@ -48,10 +51,10 @@ const handlerParams = () => _handlerParams ??= {
48
51
  va: (c) => c.vali,
49
52
  fe: () => forwardError,
50
53
  ie: (c) => {
51
- const classes = returnedErrorClasses(c.hook, c.root);
54
+ const classes = returnedErrorClasses(c.hook);
52
55
  return classes ? forwardErrorOf(classes) : forwardError;
53
56
  },
54
- fre: () => finalizeRouteError,
57
+ fre: (c) => finalizeRouteErrorOf(c.hook),
55
58
  fbr: () => fallbackResponse,
56
59
  aet: () => adoptErrorType,
57
60
  rt: (c) => c.root,
@@ -65,18 +68,24 @@ const handlerParams = () => _handlerParams ??= {
65
68
  tr: (c) => c.tracers,
66
69
  cc: (c) => c.cookieConfig
67
70
  };
71
+ /**
72
+ * `vs<i>` / `vr<i>`: status and validator of the route's i-th declared response
73
+ */
74
+ const isResponseParam = (name) => /^v[rs]\d+$/.test(name);
68
75
  function resolveHandlerParams(names, c) {
69
76
  const length = names.length;
70
77
  if (!length) return [];
71
78
  const out = new Array(length);
72
79
  const params = handlerParams();
73
80
  for (let i = 0; i < length; i++) {
74
- const resolve = params[names[i]];
75
- if (!resolve) throw new Error(`[elysia-aot]: Fail to reconstruct build, missing "${names[i]}" param`);
76
- out[i] = resolve(c);
81
+ const name = names[i];
82
+ const entry = isResponseParam(name) && [...c.vali?.response ?? []][+name.slice(2)];
83
+ const resolve = params[name];
84
+ if (!entry && !resolve) throw new Error(`[elysia-aot]: Fail to reconstruct build, missing "${name}" param`);
85
+ out[i] = entry ? entry[name[1] === "s" ? 0 : 1] : resolve(c);
77
86
  }
78
87
  return out;
79
88
  }
80
89
 
81
90
  //#endregion
82
- export { resolveHandlerParams };
91
+ export { isResponseParam, resolveHandlerParams };
@@ -3,10 +3,10 @@ import { AnyElysia } from "../../base.js";
3
3
  import { CompiledCookieConfig } from "../../cookie/config.js";
4
4
 
5
5
  //#region src/compile/handler/reconstruct.d.ts
6
- declare abstract class Reconstrct {
6
+ declare abstract class Reconstruct {
7
7
  static validator(hook: AnyLocalHook, root: AnyElysia, method: HTTPMethod, path: string, liveOnly?: boolean): any;
8
8
  static cookie(hook: AnyLocalHook, root: AnyElysia): CompiledCookieConfig;
9
9
  static trace(hook: AnyLocalHook, root: AnyElysia): any;
10
10
  }
11
11
  //#endregion
12
- export { Reconstrct };
12
+ export { Reconstruct };