elysia 2.0.0-exp.52 → 2.0.0-exp.53

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 (55) hide show
  1. package/dist/adapter/bun/index.js +1 -7
  2. package/dist/adapter/bun/index.mjs +1 -7
  3. package/dist/adapter/origin.d.ts +1 -1
  4. package/dist/adapter/origin.js +1 -1
  5. package/dist/adapter/origin.mjs +1 -1
  6. package/dist/adapter/utils.js +3 -3
  7. package/dist/adapter/utils.mjs +3 -3
  8. package/dist/base.d.ts +0 -10
  9. package/dist/base.js +50 -23
  10. package/dist/base.mjs +50 -23
  11. package/dist/compile/aot-capture.js +1 -1
  12. package/dist/compile/aot-capture.mjs +1 -1
  13. package/dist/compile/aot.d.ts +1 -1
  14. package/dist/compile/aot.js +4 -5
  15. package/dist/compile/aot.mjs +4 -5
  16. package/dist/compile/handler/frozen-validator.d.ts +1 -1
  17. package/dist/compile/handler/frozen-validator.js +1 -4
  18. package/dist/compile/handler/frozen-validator.mjs +1 -4
  19. package/dist/compile/handler/params.d.ts +2 -2
  20. package/dist/compile/handler/params.js +5 -3
  21. package/dist/compile/handler/params.mjs +5 -3
  22. package/dist/compile/lexer.d.ts +1 -1
  23. package/dist/cookie/crypto.js +6 -7
  24. package/dist/cookie/crypto.mjs +7 -8
  25. package/dist/package.js +1 -1
  26. package/dist/package.mjs +1 -1
  27. package/dist/plugin/aot/core.d.ts +4 -4
  28. package/dist/plugin/aot/core.js +1 -1
  29. package/dist/plugin/aot/core.mjs +1 -1
  30. package/dist/plugin/aot/source.d.ts +1 -1
  31. package/dist/plugin/aot/unplugin.d.ts +5 -9
  32. package/dist/plugin/aot/unplugin.js +3 -7
  33. package/dist/plugin/aot/unplugin.mjs +3 -7
  34. package/dist/schema-snapshot.js +6 -6
  35. package/dist/schema-snapshot.mjs +6 -6
  36. package/dist/sucrose.d.ts +1 -1
  37. package/dist/sucrose.js +14 -22
  38. package/dist/sucrose.mjs +15 -23
  39. package/dist/type/bridge.js +1 -2
  40. package/dist/type/bridge.mjs +1 -2
  41. package/dist/type/coerce-plan.js +2 -5
  42. package/dist/type/coerce-plan.mjs +3 -6
  43. package/dist/type/elysia/string.js +6 -6
  44. package/dist/type/elysia/string.mjs +6 -6
  45. package/dist/type/elysia/utils.js +5 -7
  46. package/dist/type/elysia/utils.mjs +6 -8
  47. package/dist/type/validator/index.js +2 -10
  48. package/dist/type/validator/index.mjs +2 -10
  49. package/dist/type/validator/validator-cache.js +5 -6
  50. package/dist/type/validator/validator-cache.mjs +6 -7
  51. package/dist/utils.d.ts +10 -1
  52. package/dist/utils.js +14 -0
  53. package/dist/utils.mjs +14 -1
  54. package/dist/ws/types.d.ts +2 -2
  55. package/package.json +1 -1
@@ -15,14 +15,8 @@ const require_route_table = require('../../route-table.js');
15
15
  * always run before the next request comes in
16
16
  * @see ../origin.ts
17
17
  *
18
- * Publish the request `Bun.serve` handed us so the pipeline can prove, before
19
- * its first suspension, that it holds the untouched original and may defer
20
- * materializing `request.signal`. The proof happens in `createFetchHandler`'s
21
- * prologue when there is a request hook, and at the compiled route's entry
22
- * probe otherwise — both inside the same synchronous frame.
23
- *
24
18
  * `finally` runs on the synchronous return of `fetch` (the returned promise is
25
- * not awaited), so the slot is live only for the handler's synchronous prologue.
19
+ * not awaited), so the slot is live only for the handler's synchronous prologue
26
20
  */
27
21
  const withOrigin = (fetch) => (request, server) => {
28
22
  require_adapter_origin.origin.request = request;
@@ -14,14 +14,8 @@ import { routeRow } from "../../route-table.mjs";
14
14
  * always run before the next request comes in
15
15
  * @see ../origin.ts
16
16
  *
17
- * Publish the request `Bun.serve` handed us so the pipeline can prove, before
18
- * its first suspension, that it holds the untouched original and may defer
19
- * materializing `request.signal`. The proof happens in `createFetchHandler`'s
20
- * prologue when there is a request hook, and at the compiled route's entry
21
- * probe otherwise — both inside the same synchronous frame.
22
- *
23
17
  * `finally` runs on the synchronous return of `fetch` (the returned promise is
24
- * not awaited), so the slot is live only for the handler's synchronous prologue.
18
+ * not awaited), so the slot is live only for the handler's synchronous prologue
25
19
  */
26
20
  const withOrigin = (fetch) => (request, server) => {
27
21
  origin.request = request;
@@ -34,7 +34,7 @@
34
34
  * A's name on the board, by the time B's turn starts, the board was already
35
35
  * erased at the end of A's turn.
36
36
  *
37
- * "But the handler is async!" the `await`s inside it run LATER, in separate
37
+ * "But the handler is async!" the `await`s inside it run LATER, in separate
38
38
  * turns. That is fine, because the check already happened: the verdict was
39
39
  * copied onto that request's own context (`'~sig'`) during the synchronous
40
40
  * part, and the code that runs after an `await` only ever reads the context,
@@ -36,7 +36,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
36
36
  * A's name on the board, by the time B's turn starts, the board was already
37
37
  * erased at the end of A's turn.
38
38
  *
39
- * "But the handler is async!" the `await`s inside it run LATER, in separate
39
+ * "But the handler is async!" the `await`s inside it run LATER, in separate
40
40
  * turns. That is fine, because the check already happened: the verdict was
41
41
  * copied onto that request's own context (`'~sig'`) during the synchronous
42
42
  * part, and the code that runs after an `await` only ever reads the context,
@@ -34,7 +34,7 @@
34
34
  * A's name on the board, by the time B's turn starts, the board was already
35
35
  * erased at the end of A's turn.
36
36
  *
37
- * "But the handler is async!" the `await`s inside it run LATER, in separate
37
+ * "But the handler is async!" the `await`s inside it run LATER, in separate
38
38
  * turns. That is fine, because the check already happened: the verdict was
39
39
  * copied onto that request's own context (`'~sig'`) during the synchronous
40
40
  * part, and the code that runs after an `await` only ever reads the context,
@@ -360,20 +360,20 @@ function createResponseHandler(handler) {
360
360
  const explicitlyBorrowed = require_adapter_response_ownership.isBorrowedResponse(response);
361
361
  const borrowed = !owned || explicitlyBorrowed;
362
362
  const mustClone = owned && explicitlyBorrowed;
363
- if (!borrowed && response.bodyUsed) throw new TypeError("Cannot reuse a consumed Response across requests — a returned Response is request-owned; call borrow(response) to mark it reusable");
363
+ if (!borrowed && response.bodyUsed) throw new TypeError("Cannot reuse a consumed Response across requests");
364
364
  if (set) {
365
365
  const status = mergeStatus(response.status, set.status);
366
366
  const statusUnchanged = status === void 0 || status === response.status;
367
367
  if (!mustClone && statusUnchanged && !set.cookie && !require_utils.isNotEmpty(set.headers)) return response;
368
368
  } else if (!mustClone) return response;
369
- if (!borrowed && response.body?.locked) throw new TypeError("Cannot patch a Response whose body is locked — release the reader, or call borrow(response) if it must be reused");
369
+ if (!borrowed && response.body?.locked) throw new TypeError("Cannot patch a Response whose body is locked");
370
370
  let body = response.body;
371
371
  if (borrowed) {
372
372
  const bodyBefore = body;
373
373
  const cloned = response.clone();
374
374
  if (explicitlyBorrowed && bodyBefore && response.body !== bodyBefore && !warnedStreamBorrows.has(response)) {
375
375
  warnedStreamBorrows.add(response);
376
- console.warn("[elysia] borrow() was called on a stream-backed Response — its entire body will stay buffered in memory for as long as the borrowed object lives, and every reuse adds a tee layer. Borrow only buffered Responses (string / ArrayBuffer / Blob bodies), or construct a fresh Response per request.");
376
+ console.warn("[elysia] borrow() was called on a stream-backed Response");
377
377
  }
378
378
  body = cloned.body && response.body ? cancelPropagatingBody(cloned.body, response.body, explicitlyBorrowed) : cloned.body;
379
379
  }
@@ -359,20 +359,20 @@ function createResponseHandler(handler) {
359
359
  const explicitlyBorrowed = isBorrowedResponse(response);
360
360
  const borrowed = !owned || explicitlyBorrowed;
361
361
  const mustClone = owned && explicitlyBorrowed;
362
- if (!borrowed && response.bodyUsed) throw new TypeError("Cannot reuse a consumed Response across requests — a returned Response is request-owned; call borrow(response) to mark it reusable");
362
+ if (!borrowed && response.bodyUsed) throw new TypeError("Cannot reuse a consumed Response across requests");
363
363
  if (set) {
364
364
  const status = mergeStatus(response.status, set.status);
365
365
  const statusUnchanged = status === void 0 || status === response.status;
366
366
  if (!mustClone && statusUnchanged && !set.cookie && !isNotEmpty(set.headers)) return response;
367
367
  } else if (!mustClone) return response;
368
- if (!borrowed && response.body?.locked) throw new TypeError("Cannot patch a Response whose body is locked — release the reader, or call borrow(response) if it must be reused");
368
+ if (!borrowed && response.body?.locked) throw new TypeError("Cannot patch a Response whose body is locked");
369
369
  let body = response.body;
370
370
  if (borrowed) {
371
371
  const bodyBefore = body;
372
372
  const cloned = response.clone();
373
373
  if (explicitlyBorrowed && bodyBefore && response.body !== bodyBefore && !warnedStreamBorrows.has(response)) {
374
374
  warnedStreamBorrows.add(response);
375
- console.warn("[elysia] borrow() was called on a stream-backed Response — its entire body will stay buffered in memory for as long as the borrowed object lives, and every reuse adds a tee layer. Borrow only buffered Responses (string / ArrayBuffer / Blob bodies), or construct a fresh Response per request.");
375
+ console.warn("[elysia] borrow() was called on a stream-backed Response");
376
376
  }
377
377
  body = cloned.body && response.body ? cancelPropagatingBody(cloned.body, response.body, explicitlyBorrowed) : cloned.body;
378
378
  }
package/dist/base.d.ts CHANGED
@@ -524,16 +524,6 @@ declare class Elysia<const in out BasePath extends string = '', const in out Sco
524
524
  parser: Metadata['parser'];
525
525
  response: Metadata['response'] & MacroContext['response'] & ElysiaHandlerToResponseSchemaAmbiguous<BeforeHandle> & ElysiaHandlerToResponseSchemaAmbiguous<AfterHandle> & ElysiaHandlerToResponseSchemaAmbiguous<ErrorHandle>;
526
526
  }, {}, Ephemeral, Volatile>) => NewElysia): Elysia<BasePath, Scope, Singleton, Definitions, Metadata, Routes & NewElysia['~Routes'], Ephemeral, Volatile>;
527
- /**
528
- * Single idempotent capability resolver-accessor (README rev 2.1). Reads
529
- * the merged `~ext.capability` channel — never mutated during a build — and
530
- * throws when a capability is used but its provider was never registered.
531
- * For `trace` the resolved view IS the nearest-root provider (merge already
532
- * keeps it); for `ws` it additionally resolves the depth-precedence base
533
- * options. Called at the start of every router build and by `compileHandler`
534
- * before it reads the frozen root, so direct-compiler paths resolve without
535
- * a prior seal.
536
- */
537
527
  ['~resolvedCapability'](kind: 'trace'): TraceCapability | undefined;
538
528
  ['~resolvedCapability'](kind: 'ws'): {
539
529
  provider: WSCapability;
package/dist/base.js CHANGED
@@ -33,9 +33,7 @@ var Elysia = class Elysia {
33
33
  #macroBaseline;
34
34
  #declaredRoutes;
35
35
  #routeSources;
36
- #cachedHistory;
37
36
  get history() {
38
- if (this.#cachedHistory) return this.#cachedHistory;
39
37
  if (this.#declaredRoutes === void 0 && this["~routeTable"]?.length) this.#materializeDeclaredRoutes();
40
38
  if (!this.#declaredRoutes?.length) return emptyHistory;
41
39
  const history = new Array(this.#declaredRoutes.length);
@@ -49,7 +47,7 @@ var Elysia = class Elysia {
49
47
  ...source === void 0 ? {} : { source }
50
48
  });
51
49
  }
52
- return this.#cachedHistory = Object.freeze(history);
50
+ return Object.freeze(history);
53
51
  }
54
52
  get ["~routes"]() {
55
53
  if (this.#declaredRoutes === void 0 && this["~routeTable"]?.length) this.#materializeDeclaredRoutes();
@@ -83,19 +81,59 @@ var Elysia = class Elysia {
83
81
  #jitRoute;
84
82
  #jitStatic;
85
83
  #jitAliases;
86
- #cachedRoutes;
87
84
  constructor(config) {
88
- this["~programId"] = require_compile_aot.createProgramId();
85
+ /**
86
+ * ! Don't tune
87
+ *
88
+ * Interesting JSC internal: These `= undefined` are load-bearing
89
+ *
90
+ * Inline slots live inside the object cell, so JSC must pick their
91
+ * count at allocation before any initializer runs
92
+ *
93
+ * Its only signal is counting `this.x =` in the ctor body;
94
+ * class-field initializers compile into a separate hidden function
95
+ * the guess never sees
96
+ *
97
+ * The cell can't grow afterwards, so once inline slots run out every
98
+ * later property spills into the butterfly, and capacity is by n^2
99
+ *
100
+ * Fields run first before ctor (here), so they take the inline slots
101
+ * these assignments reserve
102
+ *
103
+ * Don't omitted field either for monomorphic access
104
+ *
105
+ * @see test/memory/instance-footprint.test.ts
106
+ * Est. Overflow 37 -> 21 = butterfly 64 -> 32 slots = 738B -> 450B/instance
107
+ **/
89
108
  this["~config"] = config;
90
- this["~Prefix"] = config?.prefix;
91
- if (this["~Prefix"] && !this["~Prefix"].startsWith("/")) this["~Prefix"] = `/${this["~Prefix"]}`;
92
- if (config?.name) this.#hash = require_utils.fnv1a(config.seed ? `${config.name}_${typeof config.seed === "object" ? JSON.stringify(config.seed, require_utils.serializeMacroSeed) : config.seed}` : config.name);
109
+ this["~ext"] = void 0;
110
+ this["~hookChain"] = void 0;
111
+ this["~wsConfig"] = void 0;
112
+ this.server = void 0;
113
+ this["~router"] = void 0;
114
+ this["~map"] = void 0;
115
+ this["~routeTable"] = void 0;
116
+ this["~hasWS"] = void 0;
117
+ this["~hasDynamicWS"] = void 0;
118
+ this["~hasTrace"] = void 0;
119
+ this["~finalizeError"] = void 0;
120
+ this["~aotFingerprint"] = void 0;
121
+ this["~compilerSession"] = void 0;
122
+ this["~generation"] = void 0;
123
+ this["~introspect"] = void 0;
124
+ this["~scopeChild"] = void 0;
125
+ this["~scopeChildren"] = void 0;
126
+ this["~programId"] = require_compile_aot.createProgramId();
127
+ if (config) {
128
+ const { prefix, name, seed } = config;
129
+ this["~Prefix"] = prefix ? prefix.charCodeAt(0) === 47 ? prefix : `/${prefix}` : void 0;
130
+ if (name) this.#hash = require_utils.fnv1a(seed ? `${name}_${typeof seed === "object" ? JSON.stringify(seed, require_utils.serializeMacroSeed) : seed}` : name);
131
+ } else this["~Prefix"] = void 0;
93
132
  }
94
133
  get routes() {
95
- if (this.#cachedRoutes) return this.#cachedRoutes;
96
134
  if (this.#declaredRoutes === void 0 && this["~routeTable"]?.length) this.#materializeDeclaredRoutes();
97
135
  if (!this.#declaredRoutes?.length) return [];
98
- const routes = this["~routes"].map(([method, path, handler, instance, hook, appHook, inheritedChain, macroScope]) => {
136
+ return this["~routes"].map(([method, path, handler, instance, hook, appHook, inheritedChain, macroScope]) => {
99
137
  const merged = require_compile_handler_index.composeRouteHook(instance, hook, appHook, inheritedChain, this, macroScope);
100
138
  if (merged?.schemas?.length) for (const entry of merged.schemas) {
101
139
  if (!entry?.response) continue;
@@ -109,8 +147,6 @@ var Elysia = class Elysia {
109
147
  hooks: merged
110
148
  };
111
149
  });
112
- this.#cachedRoutes = routes;
113
- return routes;
114
150
  }
115
151
  decorate(typeOrNameOrDecorators, nameOrDecorators, value) {
116
152
  switch (arguments.length) {
@@ -186,7 +222,6 @@ var Elysia = class Elysia {
186
222
  scope,
187
223
  owner: this
188
224
  };
189
- this.#cachedRoutes = void 0;
190
225
  if (scope === "plugin") this.#hasPlugin = true;
191
226
  else if (scope === "global") this.#hasGlobal = true;
192
227
  if (this.#hash !== void 0) {
@@ -306,7 +341,6 @@ var Elysia = class Elysia {
306
341
  as(target) {
307
342
  this.#assertMutable("as");
308
343
  this.#as(this["~hookChain"], target === "global" ? "global" : "plugin");
309
- this.#cachedRoutes = void 0;
310
344
  return this;
311
345
  }
312
346
  #as(node, scope) {
@@ -452,7 +486,6 @@ var Elysia = class Elysia {
452
486
  scope,
453
487
  owner: this
454
488
  };
455
- this.#cachedRoutes = void 0;
456
489
  return this;
457
490
  }
458
491
  macro(macro) {
@@ -466,7 +499,6 @@ var Elysia = class Elysia {
466
499
  if (baseline?.has(key) && key in m && m[key] !== macro[key]) throw new Error(`[Elysia] Macro "${key}" can be only define once`);
467
500
  }
468
501
  Object.assign(m, macro);
469
- this.#cachedRoutes = void 0;
470
502
  require_utils.invalidateMacroEpoch();
471
503
  return this;
472
504
  }
@@ -606,7 +638,6 @@ var Elysia = class Elysia {
606
638
  this.#childrenHash.add(hash);
607
639
  (addedByThisCall ??= /* @__PURE__ */ new Set()).add(hash);
608
640
  }
609
- this.#cachedRoutes = void 0;
610
641
  if (app.#childrenHash) addedByThisCall = this.#absorbChildrenHash(app, addedByThisCall);
611
642
  if (app["~ext"]) this.#assertMacroUnique(app, addedByThisCall);
612
643
  if (app["~hasTrace"]) this["~hasTrace"] = true;
@@ -961,9 +992,7 @@ var Elysia = class Elysia {
961
992
  handler,
962
993
  this
963
994
  ]);
964
- if (this.#routerBuilt || this.#compiled !== void 0 || this.#cachedRoutes !== void 0 || this.#cachedHistory !== void 0) {
965
- this.#cachedHistory = void 0;
966
- this.#cachedRoutes = void 0;
995
+ if (this.#routerBuilt || this.#compiled !== void 0) {
967
996
  this.#compiled = void 0;
968
997
  this.#jitColdRemaining = void 0;
969
998
  this.#jitTable = void 0;
@@ -993,9 +1022,7 @@ var Elysia = class Elysia {
993
1022
  const sequence = routes.length;
994
1023
  routes.push(route);
995
1024
  if (source) (this.#routeSources ??= [])[sequence] = source;
996
- if (this.#routerBuilt || this.#compiled !== void 0 || this.#cachedRoutes !== void 0 || this.#cachedHistory !== void 0) {
997
- this.#cachedHistory = void 0;
998
- this.#cachedRoutes = void 0;
1025
+ if (this.#routerBuilt || this.#compiled !== void 0) {
999
1026
  this.#compiled = void 0;
1000
1027
  this.#jitColdRemaining = void 0;
1001
1028
  this.#jitTable = void 0;
package/dist/base.mjs CHANGED
@@ -30,9 +30,7 @@ var Elysia = class Elysia {
30
30
  #macroBaseline;
31
31
  #declaredRoutes;
32
32
  #routeSources;
33
- #cachedHistory;
34
33
  get history() {
35
- if (this.#cachedHistory) return this.#cachedHistory;
36
34
  if (this.#declaredRoutes === void 0 && this["~routeTable"]?.length) this.#materializeDeclaredRoutes();
37
35
  if (!this.#declaredRoutes?.length) return emptyHistory;
38
36
  const history = new Array(this.#declaredRoutes.length);
@@ -46,7 +44,7 @@ var Elysia = class Elysia {
46
44
  ...source === void 0 ? {} : { source }
47
45
  });
48
46
  }
49
- return this.#cachedHistory = Object.freeze(history);
47
+ return Object.freeze(history);
50
48
  }
51
49
  get ["~routes"]() {
52
50
  if (this.#declaredRoutes === void 0 && this["~routeTable"]?.length) this.#materializeDeclaredRoutes();
@@ -80,19 +78,59 @@ var Elysia = class Elysia {
80
78
  #jitRoute;
81
79
  #jitStatic;
82
80
  #jitAliases;
83
- #cachedRoutes;
84
81
  constructor(config) {
85
- this["~programId"] = createProgramId();
82
+ /**
83
+ * ! Don't tune
84
+ *
85
+ * Interesting JSC internal: These `= undefined` are load-bearing
86
+ *
87
+ * Inline slots live inside the object cell, so JSC must pick their
88
+ * count at allocation before any initializer runs
89
+ *
90
+ * Its only signal is counting `this.x =` in the ctor body;
91
+ * class-field initializers compile into a separate hidden function
92
+ * the guess never sees
93
+ *
94
+ * The cell can't grow afterwards, so once inline slots run out every
95
+ * later property spills into the butterfly, and capacity is by n^2
96
+ *
97
+ * Fields run first before ctor (here), so they take the inline slots
98
+ * these assignments reserve
99
+ *
100
+ * Don't omitted field either for monomorphic access
101
+ *
102
+ * @see test/memory/instance-footprint.test.ts
103
+ * Est. Overflow 37 -> 21 = butterfly 64 -> 32 slots = 738B -> 450B/instance
104
+ **/
86
105
  this["~config"] = config;
87
- this["~Prefix"] = config?.prefix;
88
- if (this["~Prefix"] && !this["~Prefix"].startsWith("/")) this["~Prefix"] = `/${this["~Prefix"]}`;
89
- if (config?.name) this.#hash = fnv1a(config.seed ? `${config.name}_${typeof config.seed === "object" ? JSON.stringify(config.seed, serializeMacroSeed) : config.seed}` : config.name);
106
+ this["~ext"] = void 0;
107
+ this["~hookChain"] = void 0;
108
+ this["~wsConfig"] = void 0;
109
+ this.server = void 0;
110
+ this["~router"] = void 0;
111
+ this["~map"] = void 0;
112
+ this["~routeTable"] = void 0;
113
+ this["~hasWS"] = void 0;
114
+ this["~hasDynamicWS"] = void 0;
115
+ this["~hasTrace"] = void 0;
116
+ this["~finalizeError"] = void 0;
117
+ this["~aotFingerprint"] = void 0;
118
+ this["~compilerSession"] = void 0;
119
+ this["~generation"] = void 0;
120
+ this["~introspect"] = void 0;
121
+ this["~scopeChild"] = void 0;
122
+ this["~scopeChildren"] = void 0;
123
+ this["~programId"] = createProgramId();
124
+ if (config) {
125
+ const { prefix, name, seed } = config;
126
+ this["~Prefix"] = prefix ? prefix.charCodeAt(0) === 47 ? prefix : `/${prefix}` : void 0;
127
+ if (name) this.#hash = fnv1a(seed ? `${name}_${typeof seed === "object" ? JSON.stringify(seed, serializeMacroSeed) : seed}` : name);
128
+ } else this["~Prefix"] = void 0;
90
129
  }
91
130
  get routes() {
92
- if (this.#cachedRoutes) return this.#cachedRoutes;
93
131
  if (this.#declaredRoutes === void 0 && this["~routeTable"]?.length) this.#materializeDeclaredRoutes();
94
132
  if (!this.#declaredRoutes?.length) return [];
95
- const routes = this["~routes"].map(([method, path, handler, instance, hook, appHook, inheritedChain, macroScope]) => {
133
+ return this["~routes"].map(([method, path, handler, instance, hook, appHook, inheritedChain, macroScope]) => {
96
134
  const merged = composeRouteHook(instance, hook, appHook, inheritedChain, this, macroScope);
97
135
  if (merged?.schemas?.length) for (const entry of merged.schemas) {
98
136
  if (!entry?.response) continue;
@@ -106,8 +144,6 @@ var Elysia = class Elysia {
106
144
  hooks: merged
107
145
  };
108
146
  });
109
- this.#cachedRoutes = routes;
110
- return routes;
111
147
  }
112
148
  decorate(typeOrNameOrDecorators, nameOrDecorators, value) {
113
149
  switch (arguments.length) {
@@ -183,7 +219,6 @@ var Elysia = class Elysia {
183
219
  scope,
184
220
  owner: this
185
221
  };
186
- this.#cachedRoutes = void 0;
187
222
  if (scope === "plugin") this.#hasPlugin = true;
188
223
  else if (scope === "global") this.#hasGlobal = true;
189
224
  if (this.#hash !== void 0) {
@@ -303,7 +338,6 @@ var Elysia = class Elysia {
303
338
  as(target) {
304
339
  this.#assertMutable("as");
305
340
  this.#as(this["~hookChain"], target === "global" ? "global" : "plugin");
306
- this.#cachedRoutes = void 0;
307
341
  return this;
308
342
  }
309
343
  #as(node, scope) {
@@ -449,7 +483,6 @@ var Elysia = class Elysia {
449
483
  scope,
450
484
  owner: this
451
485
  };
452
- this.#cachedRoutes = void 0;
453
486
  return this;
454
487
  }
455
488
  macro(macro) {
@@ -463,7 +496,6 @@ var Elysia = class Elysia {
463
496
  if (baseline?.has(key) && key in m && m[key] !== macro[key]) throw new Error(`[Elysia] Macro "${key}" can be only define once`);
464
497
  }
465
498
  Object.assign(m, macro);
466
- this.#cachedRoutes = void 0;
467
499
  invalidateMacroEpoch();
468
500
  return this;
469
501
  }
@@ -603,7 +635,6 @@ var Elysia = class Elysia {
603
635
  this.#childrenHash.add(hash);
604
636
  (addedByThisCall ??= /* @__PURE__ */ new Set()).add(hash);
605
637
  }
606
- this.#cachedRoutes = void 0;
607
638
  if (app.#childrenHash) addedByThisCall = this.#absorbChildrenHash(app, addedByThisCall);
608
639
  if (app["~ext"]) this.#assertMacroUnique(app, addedByThisCall);
609
640
  if (app["~hasTrace"]) this["~hasTrace"] = true;
@@ -958,9 +989,7 @@ var Elysia = class Elysia {
958
989
  handler,
959
990
  this
960
991
  ]);
961
- if (this.#routerBuilt || this.#compiled !== void 0 || this.#cachedRoutes !== void 0 || this.#cachedHistory !== void 0) {
962
- this.#cachedHistory = void 0;
963
- this.#cachedRoutes = void 0;
992
+ if (this.#routerBuilt || this.#compiled !== void 0) {
964
993
  this.#compiled = void 0;
965
994
  this.#jitColdRemaining = void 0;
966
995
  this.#jitTable = void 0;
@@ -990,9 +1019,7 @@ var Elysia = class Elysia {
990
1019
  const sequence = routes.length;
991
1020
  routes.push(route);
992
1021
  if (source) (this.#routeSources ??= [])[sequence] = source;
993
- if (this.#routerBuilt || this.#compiled !== void 0 || this.#cachedRoutes !== void 0 || this.#cachedHistory !== void 0) {
994
- this.#cachedHistory = void 0;
995
- this.#cachedRoutes = void 0;
1022
+ if (this.#routerBuilt || this.#compiled !== void 0) {
996
1023
  this.#compiled = void 0;
997
1024
  this.#jitColdRemaining = void 0;
998
1025
  this.#jitTable = void 0;
@@ -283,7 +283,7 @@ function captureBridgeFree(aot, slot, rawSchema) {
283
283
  }
284
284
  }
285
285
  function beginValidatorCapture() {
286
- if (require_compile_aot.captureImpl === void 0) throw require_compile_aot.aotActivationError;
286
+ if (require_compile_aot.captureImpl === void 0) throw require_compile_aot.aotActivationError();
287
287
  const active = require_compile_aot.CompilerState.session;
288
288
  if (active?.capture !== void 0) {
289
289
  if (active.explicitCapture) throw new Error("[elysia-aot]: A capture session is already active.");
@@ -280,7 +280,7 @@ function captureBridgeFree(aot, slot, rawSchema) {
280
280
  }
281
281
  }
282
282
  function beginValidatorCapture() {
283
- if (captureImpl === void 0) throw aotActivationError;
283
+ if (captureImpl === void 0) throw aotActivationError();
284
284
  const active = CompilerState.session;
285
285
  if (active?.capture !== void 0) {
286
286
  if (active.explicitCapture) throw new Error("[elysia-aot]: A capture session is already active.");
@@ -217,7 +217,7 @@ interface CapturedValidator {
217
217
  bridgeFree?: boolean;
218
218
  }
219
219
  /** @internal shared with `aot-capture.ts` (`beginValidatorCapture`). */
220
- declare const aotActivationError: Error;
220
+ declare const aotActivationError: () => Error;
221
221
  interface CapturedHandler {
222
222
  method: string;
223
223
  path: string;
@@ -36,9 +36,8 @@ function endCompilerSession(app, session, failed = false) {
36
36
  }
37
37
  const getCompilerSession = () => activeSession;
38
38
  let reconstructImpl;
39
- const reconstructActivationError = /* @__PURE__ */ new Error("Elysia AOT reconstruct module is not activated.");
40
39
  function reconstruct() {
41
- if (reconstructImpl === void 0) throw reconstructActivationError;
40
+ if (reconstructImpl === void 0) throw new Error("Elysia AOT reconstruct module is not activated");
42
41
  return reconstructImpl;
43
42
  }
44
43
  let registered;
@@ -161,7 +160,7 @@ function captureEntry({ method, path, slot }) {
161
160
  return e;
162
161
  }
163
162
  /** @internal shared with `aot-capture.ts` (`beginValidatorCapture`). */
164
- const aotActivationError = /* @__PURE__ */ new Error("Elysia AOT capture module is not activated.");
163
+ const aotActivationError = () => /* @__PURE__ */ new Error("Elysia AOT capture module is not activated.");
165
164
  function captureHandler(v) {
166
165
  if (!isValidatorCapturing()) return;
167
166
  const session = activeSession;
@@ -176,11 +175,11 @@ const captureGet = (loc) => activeSession?.capture?.get(`${loc.method}_${loc.pat
176
175
  const isAotBuildEnv = () => !!require_universal_env.env.ELYSIA_AOT_BUILD;
177
176
  const isValidatorCapturing = () => {
178
177
  if (activeSession?.capture !== void 0) {
179
- if (captureImpl === void 0) throw aotActivationError;
178
+ if (captureImpl === void 0) throw aotActivationError();
180
179
  return true;
181
180
  }
182
181
  if (isAotBuildEnv()) {
183
- if (captureImpl === void 0) throw aotActivationError;
182
+ if (captureImpl === void 0) throw aotActivationError();
184
183
  return true;
185
184
  }
186
185
  return false;
@@ -35,9 +35,8 @@ function endCompilerSession(app, session, failed = false) {
35
35
  }
36
36
  const getCompilerSession = () => activeSession;
37
37
  let reconstructImpl;
38
- const reconstructActivationError = /* @__PURE__ */ new Error("Elysia AOT reconstruct module is not activated.");
39
38
  function reconstruct() {
40
- if (reconstructImpl === void 0) throw reconstructActivationError;
39
+ if (reconstructImpl === void 0) throw new Error("Elysia AOT reconstruct module is not activated");
41
40
  return reconstructImpl;
42
41
  }
43
42
  let registered;
@@ -160,7 +159,7 @@ function captureEntry({ method, path, slot }) {
160
159
  return e;
161
160
  }
162
161
  /** @internal shared with `aot-capture.ts` (`beginValidatorCapture`). */
163
- const aotActivationError = /* @__PURE__ */ new Error("Elysia AOT capture module is not activated.");
162
+ const aotActivationError = () => /* @__PURE__ */ new Error("Elysia AOT capture module is not activated.");
164
163
  function captureHandler(v) {
165
164
  if (!isValidatorCapturing()) return;
166
165
  const session = activeSession;
@@ -175,11 +174,11 @@ const captureGet = (loc) => activeSession?.capture?.get(`${loc.method}_${loc.pat
175
174
  const isAotBuildEnv = () => !!env.ELYSIA_AOT_BUILD;
176
175
  const isValidatorCapturing = () => {
177
176
  if (activeSession?.capture !== void 0) {
178
- if (captureImpl === void 0) throw aotActivationError;
177
+ if (captureImpl === void 0) throw aotActivationError();
179
178
  return true;
180
179
  }
181
180
  if (isAotBuildEnv()) {
182
- if (captureImpl === void 0) throw aotActivationError;
181
+ if (captureImpl === void 0) throw aotActivationError();
183
182
  return true;
184
183
  }
185
184
  return false;
@@ -4,7 +4,7 @@ import { AnyElysia } from "../../base.js";
4
4
 
5
5
  //#region src/compile/handler/frozen-validator.d.ts
6
6
  declare const isBridgeNotInitialized: (error: unknown) => boolean;
7
- /** `{ check, clean?, decode? }` the slot's compiled predicate + cleaner. */
7
+ /** `{ check, clean?, decode? }` the slot's compiled predicate + cleaner. */
8
8
  interface SlotCheckClean {
9
9
  check: (value: unknown) => boolean;
10
10
  clean?: (value: unknown) => unknown;
@@ -200,10 +200,7 @@ var FrozenSlotValidator = class {
200
200
  /**
201
201
  * The JIT/frozen slot validator: the reconstruct-free `FrozenSlotValidator`
202
202
  * base plus the codec/inner-codec branch re-added via the `buildCheckClean`
203
- * override.
204
- * The only reorder — `this.hasCodec` is set by the base ctor before this runs,
205
- * where the original set it after the `frozen.ic` side-effect — is unobservable
206
- * (`reconstructInnerCodecs` neither reads nor sets `hasCodec`).
203
+ * override
207
204
  */
208
205
  var CodecFrozenSlotValidator = class extends FrozenSlotValidator {
209
206
  buildCheckClean(frozen, schema, raw, normalize) {
@@ -199,10 +199,7 @@ var FrozenSlotValidator = class {
199
199
  /**
200
200
  * The JIT/frozen slot validator: the reconstruct-free `FrozenSlotValidator`
201
201
  * base plus the codec/inner-codec branch re-added via the `buildCheckClean`
202
- * override.
203
- * The only reorder — `this.hasCodec` is set by the base ctor before this runs,
204
- * where the original set it after the `frozen.ic` side-effect — is unobservable
205
- * (`reconstructInnerCodecs` neither reads nor sets `hasCodec`).
202
+ * override
206
203
  */
207
204
  var CodecFrozenSlotValidator = class extends FrozenSlotValidator {
208
205
  buildCheckClean(frozen, schema, raw, normalize) {
@@ -22,7 +22,7 @@ interface HandlerParamContext {
22
22
  }
23
23
  type Resolver = (c: HandlerParamContext) => unknown;
24
24
  /** @internal exported for test/aot/param-descriptor.test.ts */
25
- declare const HANDLER_PARAMS: Record<string, Resolver>;
25
+ declare const handlerParams: () => Record<string, Resolver>;
26
26
  declare function resolveHandlerParams(names: string[], c: HandlerParamContext): unknown[];
27
27
  //#endregion
28
- export { HANDLER_PARAMS, resolveHandlerParams };
28
+ export { handlerParams, resolveHandlerParams };
@@ -9,8 +9,9 @@ const require_handler_utils = require('../../handler/utils.js');
9
9
  const require_compile_handler_utils = require('./utils.js');
10
10
 
11
11
  //#region src/compile/handler/params.ts
12
+ let _handlerParams;
12
13
  /** @internal exported for test/aot/param-descriptor.test.ts */
13
- const HANDLER_PARAMS = {
14
+ const handlerParams = () => _handlerParams ??= {
14
15
  pf: (c) => c.parse.formData,
15
16
  pj: (c) => c.parse.json,
16
17
  pu: (c) => c.parse.urlencoded,
@@ -63,8 +64,9 @@ function resolveHandlerParams(names, c) {
63
64
  const length = names.length;
64
65
  if (!length) return [];
65
66
  const out = new Array(length);
67
+ const params = handlerParams();
66
68
  for (let i = 0; i < length; i++) {
67
- const resolve = HANDLER_PARAMS[names[i]];
69
+ const resolve = params[names[i]];
68
70
  if (!resolve) throw new Error(`[elysia-aot]: Fail to reconstruct build, missing "${names[i]}" param`);
69
71
  out[i] = resolve(c);
70
72
  }
@@ -72,5 +74,5 @@ function resolveHandlerParams(names, c) {
72
74
  }
73
75
 
74
76
  //#endregion
75
- exports.HANDLER_PARAMS = HANDLER_PARAMS;
77
+ exports.handlerParams = handlerParams;
76
78
  exports.resolveHandlerParams = resolveHandlerParams;
@@ -8,8 +8,9 @@ import { emptyResponse, finalizeRouteError, forwardError } from "../../handler/u
8
8
  import { armEntryAbort, cloneResponse, getQueryParseChannels, hasRequestBody, replaceDeriveContext, runBeforeHandlePrefix } from "./utils.mjs";
9
9
 
10
10
  //#region src/compile/handler/params.ts
11
+ let _handlerParams;
11
12
  /** @internal exported for test/aot/param-descriptor.test.ts */
12
- const HANDLER_PARAMS = {
13
+ const handlerParams = () => _handlerParams ??= {
13
14
  pf: (c) => c.parse.formData,
14
15
  pj: (c) => c.parse.json,
15
16
  pu: (c) => c.parse.urlencoded,
@@ -62,8 +63,9 @@ function resolveHandlerParams(names, c) {
62
63
  const length = names.length;
63
64
  if (!length) return [];
64
65
  const out = new Array(length);
66
+ const params = handlerParams();
65
67
  for (let i = 0; i < length; i++) {
66
- const resolve = HANDLER_PARAMS[names[i]];
68
+ const resolve = params[names[i]];
67
69
  if (!resolve) throw new Error(`[elysia-aot]: Fail to reconstruct build, missing "${names[i]}" param`);
68
70
  out[i] = resolve(c);
69
71
  }
@@ -71,4 +73,4 @@ function resolveHandlerParams(names, c) {
71
73
  }
72
74
 
73
75
  //#endregion
74
- export { HANDLER_PARAMS, resolveHandlerParams };
76
+ export { handlerParams, resolveHandlerParams };
@@ -1,5 +1,5 @@
1
1
  //#region src/compile/lexer.d.ts
2
- declare const isSpace: (ch: string) => ch is "\n" | " " | "\t" | "\r";
2
+ declare const isSpace: (ch: string) => ch is " " | "\n" | "\t" | "\r";
3
3
  declare const isIdentChar: (ch: string) => boolean;
4
4
  declare const isIdentCharCode: (code: number) => boolean;
5
5
  declare function skipString(src: string, start: number): number;