elysia 2.0.0-beta.21 → 2.0.0-beta.23
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.
- package/dist/_virtual/_rolldown/runtime.mjs +1 -0
- package/dist/adapter/bun/index.d.ts +6 -8
- package/dist/adapter/bun/index.js +6 -8
- package/dist/adapter/bun/index.mjs +7 -8
- package/dist/adapter/constants.mjs +1 -0
- package/dist/adapter/default-headers.mjs +1 -0
- package/dist/adapter/index.mjs +1 -0
- package/dist/adapter/origin.mjs +1 -0
- package/dist/adapter/response-ownership.mjs +1 -0
- package/dist/adapter/skip-clone.mjs +1 -0
- package/dist/adapter/types.mjs +1 -0
- package/dist/adapter/utils.d.ts +5 -8
- package/dist/adapter/utils.js +24 -18
- package/dist/adapter/utils.mjs +25 -18
- package/dist/adapter/web-standard/handler.mjs +2 -1
- package/dist/adapter/web-standard/index.mjs +1 -0
- package/dist/adapter/web-standard/utils.mjs +1 -0
- package/dist/base.d.ts +118 -69
- package/dist/base.js +214 -194
- package/dist/base.mjs +221 -200
- package/dist/compile/aot-capture.js +2 -2
- package/dist/compile/aot-capture.mjs +4 -3
- package/dist/compile/aot-emit.js +7 -8
- package/dist/compile/aot-emit.mjs +8 -8
- package/dist/compile/aot-reconstruct.mjs +3 -2
- package/dist/compile/aot.d.ts +3 -3
- package/dist/compile/aot.js +5 -5
- package/dist/compile/aot.mjs +6 -5
- package/dist/compile/handler/descriptor.d.ts +2 -5
- package/dist/compile/handler/descriptor.js +12 -17
- package/dist/compile/handler/descriptor.mjs +16 -21
- package/dist/compile/handler/frozen-validator.d.ts +2 -2
- package/dist/compile/handler/frozen-validator.js +3 -3
- package/dist/compile/handler/frozen-validator.mjs +4 -3
- package/dist/compile/handler/index.d.ts +3 -1
- package/dist/compile/handler/index.js +78 -118
- package/dist/compile/handler/index.mjs +84 -125
- package/dist/compile/handler/jit.d.ts +12 -12
- package/dist/compile/handler/jit.js +60 -43
- package/dist/compile/handler/jit.mjs +63 -47
- package/dist/compile/handler/params.d.ts +5 -1
- package/dist/compile/handler/params.js +14 -5
- package/dist/compile/handler/params.mjs +16 -7
- package/dist/compile/handler/reconstruct.d.ts +2 -2
- package/dist/compile/handler/reconstruct.js +2 -2
- package/dist/compile/handler/reconstruct.mjs +3 -2
- package/dist/compile/handler/static-clone-resolver.mjs +1 -0
- package/dist/compile/handler/utils.d.ts +13 -7
- package/dist/compile/handler/utils.js +75 -52
- package/dist/compile/handler/utils.mjs +77 -54
- package/dist/compile/jit-probe.mjs +1 -0
- package/dist/compile/lexer.js +4 -4
- package/dist/compile/lexer.mjs +5 -4
- package/dist/compile/utils.d.ts +2 -1
- package/dist/compile/utils.js +8 -3
- package/dist/compile/utils.mjs +8 -3
- package/dist/compiled.mjs +1 -0
- package/dist/constants.mjs +1 -0
- package/dist/context.d.ts +1 -1
- package/dist/context.js +1 -0
- package/dist/context.mjs +3 -1
- package/dist/cookie/config.d.ts +2 -2
- package/dist/cookie/config.js +21 -26
- package/dist/cookie/config.mjs +22 -26
- package/dist/cookie/cookie.mjs +1 -0
- package/dist/cookie/crypto.mjs +1 -0
- package/dist/cookie/error.mjs +1 -0
- package/dist/cookie/lib.mjs +1 -0
- package/dist/cookie/serialize.mjs +1 -0
- package/dist/cookie/types.mjs +1 -0
- package/dist/cookie/utils.d.ts +1 -1
- package/dist/cookie/utils.js +64 -45
- package/dist/cookie/utils.mjs +66 -46
- package/dist/error.d.ts +10 -6
- package/dist/error.js +22 -6
- package/dist/error.mjs +25 -9
- package/dist/generation.mjs +1 -0
- package/dist/handler/error.d.ts +12 -15
- package/dist/handler/error.js +43 -40
- package/dist/handler/error.mjs +45 -41
- package/dist/handler/fetch.js +59 -21
- package/dist/handler/fetch.mjs +61 -22
- package/dist/handler/utils.d.ts +16 -3
- package/dist/handler/utils.js +14 -13
- package/dist/handler/utils.mjs +16 -15
- package/dist/index.d.ts +9 -9
- package/dist/index.js +1 -0
- package/dist/index.mjs +3 -2
- package/dist/memory.mjs +1 -0
- package/dist/package.js +1 -1
- package/dist/package.mjs +2 -1
- package/dist/parse-query.js +76 -76
- package/dist/parse-query.mjs +77 -76
- package/dist/plugin/aot/bun.mjs +1 -0
- package/dist/plugin/aot/core.d.ts +1 -1
- package/dist/plugin/aot/core.js +7 -4
- package/dist/plugin/aot/core.mjs +8 -5
- package/dist/plugin/aot/esbuild.mjs +1 -0
- package/dist/plugin/aot/rspack-loader.mjs +1 -0
- package/dist/plugin/aot/rspack.mjs +1 -0
- package/dist/plugin/aot/treeshake.mjs +1 -0
- package/dist/plugin/aot/unplugin.mjs +4 -3
- package/dist/plugin/aot/vite.mjs +1 -0
- package/dist/plugin/aot/worker.mjs +1 -0
- package/dist/plugin/auto-head.mjs +1 -0
- package/dist/plugin/trace.mjs +1 -0
- package/dist/plugin/websocket.mjs +1 -0
- package/dist/route-table.mjs +1 -0
- package/dist/schema-snapshot.js +28 -3
- package/dist/schema-snapshot.mjs +29 -3
- package/dist/sucrose.d.ts +2 -2
- package/dist/sucrose.js +11 -11
- package/dist/sucrose.mjs +12 -11
- package/dist/trace.js +8 -10
- package/dist/trace.mjs +10 -11
- package/dist/type/bridge-live.d.ts +1 -1
- package/dist/type/bridge-live.mjs +1 -0
- package/dist/type/bridge.d.ts +1 -1
- package/dist/type/bridge.mjs +1 -0
- package/dist/type/coerce-plan.mjs +1 -0
- package/dist/type/coerce.d.ts +1 -1
- package/dist/type/coerce.mjs +1 -0
- package/dist/type/compat.mjs +1 -0
- package/dist/type/constants.d.ts +1 -1
- package/dist/type/constants.mjs +1 -0
- package/dist/type/elysia/accelerate.mjs +1 -0
- package/dist/type/elysia/array-buffer.d.ts +3 -2
- package/dist/type/elysia/array-buffer.js +5 -5
- package/dist/type/elysia/array-buffer.mjs +6 -5
- package/dist/type/elysia/array-string.mjs +1 -0
- package/dist/type/elysia/array.mjs +1 -0
- package/dist/type/elysia/boolean-string.mjs +1 -0
- package/dist/type/elysia/boolean.mjs +1 -0
- package/dist/type/elysia/cookie.mjs +1 -0
- package/dist/type/elysia/date.mjs +1 -0
- package/dist/type/elysia/file-type.mjs +1 -0
- package/dist/type/elysia/file.mjs +1 -0
- package/dist/type/elysia/files.mjs +1 -0
- package/dist/type/elysia/form.mjs +1 -0
- package/dist/type/elysia/integer-string.mjs +1 -0
- package/dist/type/elysia/integer.mjs +1 -0
- package/dist/type/elysia/intersect.mjs +1 -0
- package/dist/type/elysia/json-string.mjs +1 -0
- package/dist/type/elysia/keep-config.js +8 -8
- package/dist/type/elysia/keep-config.mjs +9 -8
- package/dist/type/elysia/maybe-empty.mjs +1 -0
- package/dist/type/elysia/no-validate.mjs +1 -0
- package/dist/type/elysia/nullable.mjs +1 -0
- package/dist/type/elysia/number.mjs +1 -0
- package/dist/type/elysia/numeric-enum.d.ts +4 -2
- package/dist/type/elysia/numeric-enum.mjs +1 -0
- package/dist/type/elysia/numeric.mjs +1 -0
- package/dist/type/elysia/object-string.mjs +1 -0
- package/dist/type/elysia/object.mjs +1 -0
- package/dist/type/elysia/optional.mjs +1 -0
- package/dist/type/elysia/problem.mjs +1 -0
- package/dist/type/elysia/string.mjs +1 -0
- package/dist/type/elysia/uint8-array.d.ts +2 -1
- package/dist/type/elysia/uint8-array.js +2 -2
- package/dist/type/elysia/uint8-array.mjs +3 -2
- package/dist/type/elysia/union-enum.mjs +1 -0
- package/dist/type/elysia/union.mjs +1 -0
- package/dist/type/elysia/utils.js +3 -3
- package/dist/type/elysia/utils.mjs +4 -3
- package/dist/type/exports.mjs +1 -0
- package/dist/type/index.mjs +2 -1
- package/dist/type/shared.mjs +1 -0
- package/dist/type/sync-require.mjs +1 -0
- package/dist/type/typebox-system-lite.mjs +1 -0
- package/dist/type/typebox-system-require.mjs +1 -0
- package/dist/type/typebox-type-live.mjs +1 -0
- package/dist/type/typebox-value-live.mjs +1 -0
- package/dist/type/typebox-value-ops.mjs +1 -0
- package/dist/type/typebox-value.mjs +1 -0
- package/dist/type/types.d.ts +1 -1
- package/dist/type/types.mjs +1 -0
- package/dist/type/utils.mjs +1 -0
- package/dist/type/validator/clean-safe.mjs +1 -0
- package/dist/type/validator/custom-error.js +41 -33
- package/dist/type/validator/custom-error.mjs +42 -33
- package/dist/type/validator/default-precompute.d.ts +2 -2
- package/dist/type/validator/default-precompute.js +10 -11
- package/dist/type/validator/default-precompute.mjs +13 -13
- package/dist/type/validator/exact-mirror.mjs +1 -0
- package/dist/type/validator/frozen-check.js +7 -7
- package/dist/type/validator/frozen-check.mjs +8 -7
- package/dist/type/validator/index.d.ts +2 -2
- package/dist/type/validator/index.js +4 -8
- package/dist/type/validator/index.mjs +5 -8
- package/dist/type/validator/string-codec-aot.d.ts +1 -1
- package/dist/type/validator/string-codec-aot.mjs +1 -0
- package/dist/type/validator/validator-cache.js +18 -18
- package/dist/type/validator/validator-cache.mjs +19 -18
- package/dist/types.d.ts +108 -70
- package/dist/types.mjs +1 -0
- package/dist/universal/constants.mjs +1 -0
- package/dist/universal/file.mjs +1 -0
- package/dist/universal/index.mjs +1 -0
- package/dist/universal/is-production.mjs +1 -0
- package/dist/universal/server.mjs +1 -0
- package/dist/utils.d.ts +49 -31
- package/dist/utils.js +221 -109
- package/dist/utils.mjs +215 -106
- package/dist/validator/index.d.ts +3 -3
- package/dist/validator/index.js +4 -4
- package/dist/validator/index.mjs +5 -4
- package/dist/validator/route.d.ts +2 -2
- package/dist/validator/route.mjs +1 -0
- package/dist/ws/context.js +1 -1
- package/dist/ws/context.mjs +2 -1
- package/dist/ws/index.mjs +1 -0
- package/dist/ws/parser.mjs +1 -0
- package/dist/ws/route.js +34 -25
- package/dist/ws/route.mjs +40 -30
- package/dist/ws/types.d.ts +2 -3
- package/dist/ws/types.mjs +1 -0
- 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
|
|
11
|
-
*
|
|
12
|
-
*
|
|
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
|
|
23
|
-
*
|
|
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
|
|
32
|
-
* lane
|
|
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
|
|
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.
|
|
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
|
|
197
|
-
const abortCheck = () => abortOn ? plain(abortSchedule ||
|
|
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 && !
|
|
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 && !
|
|
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",
|
|
353
|
-
const validateExpr = `_ck=${
|
|
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)
|
|
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
|
-
|
|
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,
|
|
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
|
|
22
|
-
*
|
|
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
|
|
31
|
-
* lane
|
|
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
|
|
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,
|
|
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
|
|
196
|
-
const abortCheck = () => abortOn ? plain(abortSchedule ||
|
|
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 && !
|
|
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 && !
|
|
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",
|
|
352
|
-
const validateExpr = `_ck=${
|
|
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)
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
|
76
|
-
|
|
77
|
-
|
|
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,
|
|
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
|
|
54
|
+
const classes = returnedErrorClasses(c.hook);
|
|
52
55
|
return classes ? forwardErrorOf(classes) : forwardError;
|
|
53
56
|
},
|
|
54
|
-
fre: () =>
|
|
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
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
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 {
|
|
12
|
+
export { Reconstruct };
|