@solidjs/web 2.0.0-rc.4 → 2.0.0-rc.6

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 (61) hide show
  1. package/dist/dev.cjs +163 -36
  2. package/dist/dev.js +161 -37
  3. package/dist/server.cjs +178 -37
  4. package/dist/server.js +177 -38
  5. package/dist/web.cjs +143 -36
  6. package/dist/web.js +141 -37
  7. package/frames/dist/client.cjs +41 -8
  8. package/frames/dist/client.dev.cjs +41 -8
  9. package/frames/dist/client.dev.js +41 -8
  10. package/frames/dist/client.js +41 -8
  11. package/frames/dist/server.cjs +497 -44
  12. package/frames/dist/server.js +497 -44
  13. package/package.json +2 -2
  14. package/serialization/dist/decode.cjs +4 -2
  15. package/serialization/dist/decode.js +4 -2
  16. package/serialization/dist/serialization.cjs +12 -8
  17. package/serialization/dist/serialization.js +12 -8
  18. package/serialization/types/index.d.ts +7 -0
  19. package/serialization/types/serializer-decode.d.ts +14 -1
  20. package/serialization/types/serializer.d.ts +7 -0
  21. package/serialization/types-cjs/index.d.cts +7 -0
  22. package/serialization/types-cjs/serializer-decode.d.cts +14 -1
  23. package/serialization/types-cjs/serializer.d.cts +7 -0
  24. package/server-functions/dist/client.cjs +164 -35
  25. package/server-functions/dist/client.js +161 -36
  26. package/server-functions/dist/server.cjs +899 -136
  27. package/server-functions/dist/server.dev.cjs +919 -136
  28. package/server-functions/dist/server.dev.js +915 -137
  29. package/server-functions/dist/server.js +895 -137
  30. package/types/client.d.ts +2 -1
  31. package/types/constants.d.ts +3 -1
  32. package/types/cookies.d.ts +6 -14
  33. package/types/frames/frame-client.d.ts +4 -0
  34. package/types/frames/serializer-decode.d.ts +14 -1
  35. package/types/frames/serializer.d.ts +7 -0
  36. package/types/jsx.d.ts +11 -16
  37. package/types/response.d.ts +11 -0
  38. package/types/serializer-decode.d.ts +14 -1
  39. package/types/serializer.d.ts +7 -0
  40. package/types/server-functions/client.d.ts +22 -2
  41. package/types/server-functions/flash.d.ts +9 -0
  42. package/types/server-functions/server.d.ts +131 -11
  43. package/types/server-functions/shared.d.ts +77 -14
  44. package/types/server-mock.d.ts +17 -2
  45. package/types/server.d.ts +16 -2
  46. package/types-cjs/client.d.cts +2 -1
  47. package/types-cjs/constants.d.cts +3 -1
  48. package/types-cjs/cookies.d.cts +6 -14
  49. package/types-cjs/frames/frame-client.d.cts +4 -0
  50. package/types-cjs/frames/serializer-decode.d.cts +14 -1
  51. package/types-cjs/frames/serializer.d.cts +7 -0
  52. package/types-cjs/jsx.d.cts +11 -16
  53. package/types-cjs/response.d.cts +11 -0
  54. package/types-cjs/serializer-decode.d.cts +14 -1
  55. package/types-cjs/serializer.d.cts +7 -0
  56. package/types-cjs/server-functions/client.d.cts +22 -2
  57. package/types-cjs/server-functions/flash.d.cts +9 -0
  58. package/types-cjs/server-functions/server.d.cts +131 -11
  59. package/types-cjs/server-functions/shared.d.cts +77 -14
  60. package/types-cjs/server-mock.d.cts +17 -2
  61. package/types-cjs/server.d.cts +16 -2
@@ -1,5 +1,15 @@
1
1
  import { sharedConfig } from 'solid-js';
2
2
 
3
+ const COMPOSED_BODY_FRAMING = /*#__PURE__*/new Set(["content-length", "content-encoding", "transfer-encoding"]);
4
+ function isHttpNavigationTarget(target) {
5
+ try {
6
+ const protocol = new URL(target, "http://base.invalid").protocol;
7
+ return protocol === "http:" || protocol === "https:";
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+
3
13
  const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
4
14
  function isResponseEnvelope(value) {
5
15
  return !!(value && typeof value === "object" && value[ENVELOPE]);
@@ -9,6 +19,8 @@ function isSafeError(value) {
9
19
  return !!(value && (typeof value === "object" || typeof value === "function") && value[SAFE_ERROR]);
10
20
  }
11
21
  const REVALIDATE_HEADER = "X-Revalidate";
22
+ const RESPONSE_HEADER_VALUE_LIMIT = 4096;
23
+ const NULL_BODY_STATUSES = new Set([204, 205, 304]);
12
24
 
13
25
  const SERVER_FUNCTION_METADATA = Symbol.for("solid.ServerFunctionMetadata");
14
26
  function getServerFunctionMetadata(fn) {
@@ -88,6 +100,7 @@ function serializeCookie(name, value, options = {}) {
88
100
  if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
89
101
  if (options.httpOnly) cookie += "; HttpOnly";
90
102
  if (options.secure) cookie += "; Secure";
103
+ if (options.partitioned) cookie += "; Partitioned";
91
104
  if (options.sameSite) {
92
105
  const sameSite = options.sameSite.toLowerCase();
93
106
  cookie += `; SameSite=${sameSite === "none" ? "None" : sameSite === "strict" ? "Strict" : "Lax"}`;
@@ -112,8 +125,23 @@ function configureServerFunctionsCodec(codec) {
112
125
  function getServerFunctionsCodec() {
113
126
  return codecConfig.codec;
114
127
  }
115
- function subscribeFlightData(consumer) {
128
+ const UNNAMED_FLIGHT_SOURCE = "true";
129
+ const flightConfig = {
130
+ consumers: new Map()
131
+ };
132
+ function assertFlightSource(source) {
133
+ if (source === UNNAMED_FLIGHT_SOURCE || source === "" || source.includes(",")) {
134
+ throw new TypeError(`Invalid flight data source id "${source}": ids ride the ` + `${SINGLE_FLIGHT_HEADER} header as a comma-separated list, and "true" is ` + `reserved for the unnamed registration (the bare consumer/hook signatures).`);
135
+ }
136
+ }
137
+ function subscribeFlightData(sourceOrConsumer, maybeConsumer) {
138
+ const named = typeof sourceOrConsumer === "string";
139
+ if (named) assertFlightSource(sourceOrConsumer);
140
+ const source = named ? sourceOrConsumer : UNNAMED_FLIGHT_SOURCE;
141
+ const consumer = named ? maybeConsumer : sourceOrConsumer;
142
+ flightConfig.consumers.set(source, consumer);
116
143
  return () => {
144
+ if (flightConfig.consumers.get(source) === consumer) flightConfig.consumers.delete(source);
117
145
  };
118
146
  }
119
147
  function serverFunctionAddress(endpoint, id) {
@@ -125,10 +153,18 @@ function parseServerFunctionAddress(pathname, endpoint) {
125
153
  if (!pathname.startsWith(mount)) return null;
126
154
  const rest = pathname.slice(mount.length);
127
155
  if (!rest.startsWith("/")) return null;
128
- const segment = rest.slice(1);
156
+ let segment = rest.slice(1);
157
+ let data = false;
158
+ if (segment.startsWith("data/")) {
159
+ segment = segment.slice(5);
160
+ data = true;
161
+ }
129
162
  if (!segment || segment.includes("/")) return null;
130
163
  try {
131
- return decodeURIComponent(segment);
164
+ return {
165
+ id: decodeURIComponent(segment),
166
+ data
167
+ };
132
168
  } catch {
133
169
  return null;
134
170
  }
@@ -160,6 +196,28 @@ function decodeErrorHeaderValue(value) {
160
196
  }
161
197
  const INSTANCE_HEADER = "X-Server-Function-Instance";
162
198
  const BODY_FORMAT_HEADER = "X-Server-Function-Format";
199
+ const UNKNOWN_HEADER = "X-Server-Function-Unknown";
200
+ const REDIRECT_HEADER = "X-Server-Function-Redirect";
201
+ function decodeRedirectHeaderValue(value) {
202
+ if (typeof value !== "string") return undefined;
203
+ const at = value.indexOf(" ");
204
+ if (at < 0) return undefined;
205
+ const status = Number(value.slice(0, at));
206
+ const url = value.slice(at + 1);
207
+ if (!Number.isInteger(status) || !url) return undefined;
208
+ if (status !== 301 && status !== 302 && status !== 303 && status !== 307 && status !== 308) return undefined;
209
+ let parsed;
210
+ try {
211
+ parsed = new URL(url);
212
+ } catch {
213
+ return undefined;
214
+ }
215
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return undefined;
216
+ return {
217
+ status,
218
+ url
219
+ };
220
+ }
163
221
  const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
164
222
  const FILE_FORM_KEY = "__server_function_file__";
165
223
  const BodyFormat = {
@@ -202,7 +260,11 @@ function isJSONSafe(value) {
202
260
  const proto = Object.getPrototypeOf(v);
203
261
  if (proto !== Object.prototype && proto !== null) return false;
204
262
  if (Symbol.asyncIterator in v || Symbol.iterator in v) return false;
205
- for (const k in v) stack.push(v[k]);
263
+ for (const k in v) {
264
+ const descriptor = Object.getOwnPropertyDescriptor(v, k);
265
+ if (descriptor === undefined || !("value" in descriptor)) return false;
266
+ stack.push(descriptor.value);
267
+ }
206
268
  }
207
269
  }
208
270
  return true;
@@ -311,18 +373,34 @@ function createChunk(data) {
311
373
  class ChunkReader {
312
374
  constructor(stream) {
313
375
  this.reader = stream.getReader();
314
- this.buffer = new Uint8Array(0);
376
+ this.store = new Uint8Array(0);
377
+ this.buffer = this.store;
315
378
  this.done = false;
316
379
  }
317
380
  async readChunk() {
318
381
  const chunk = await this.reader.read();
319
- if (!chunk.done) {
320
- const newBuffer = new Uint8Array(this.buffer.length + chunk.value.length);
321
- newBuffer.set(this.buffer);
322
- newBuffer.set(chunk.value, this.buffer.length);
323
- this.buffer = newBuffer;
324
- } else {
382
+ if (chunk.done) {
325
383
  this.done = true;
384
+ return;
385
+ }
386
+ const incoming = chunk.value;
387
+ const store = this.store;
388
+ const start = this.buffer.byteOffset;
389
+ const end = start + this.buffer.length;
390
+ const needed = this.buffer.length + incoming.length;
391
+ if (end + incoming.length <= store.length) {
392
+ store.set(incoming, end);
393
+ this.buffer = store.subarray(start, end + incoming.length);
394
+ } else if (needed <= store.length) {
395
+ store.copyWithin(0, start, end);
396
+ store.set(incoming, this.buffer.length);
397
+ this.buffer = store.subarray(0, needed);
398
+ } else {
399
+ const grown = new Uint8Array(Math.max(needed, store.length * 2));
400
+ grown.set(this.buffer);
401
+ grown.set(incoming, this.buffer.length);
402
+ this.store = grown;
403
+ this.buffer = grown.subarray(0, needed);
326
404
  }
327
405
  }
328
406
  async next() {
@@ -364,6 +442,27 @@ class ChunkReader {
364
442
  }
365
443
  }
366
444
  }
445
+ const ERROR_TRAILER_PREFIX = "!";
446
+ function encodeErrorTrailer(error) {
447
+ const shaped = error instanceof Error ? error : new Error(String(error));
448
+ return ERROR_TRAILER_PREFIX + JSON.stringify(shaped.name && shaped.name !== "Error" ? {
449
+ name: shaped.name,
450
+ message: shaped.message
451
+ } : {
452
+ message: shaped.message
453
+ });
454
+ }
455
+ function errorFromTrailer(payload) {
456
+ let shape;
457
+ try {
458
+ shape = JSON.parse(payload.slice(1));
459
+ } catch {
460
+ shape = null;
461
+ }
462
+ const error = new Error(shape && typeof shape.message === "string" ? shape.message : "Server function result could not be delivered.");
463
+ if (shape && typeof shape.name === "string") error.name = shape.name;
464
+ return error;
465
+ }
367
466
  async function deserializeStream(source, codecOptions) {
368
467
  if (!source.body) {
369
468
  throw new Error("missing body");
@@ -371,11 +470,17 @@ async function deserializeStream(source, codecOptions) {
371
470
  const reader = new ChunkReader(source.body);
372
471
  const result = await reader.next();
373
472
  if (!result.done) {
473
+ if (result.value.startsWith(ERROR_TRAILER_PREFIX)) {
474
+ throw errorFromTrailer(result.value);
475
+ }
374
476
  const {
375
477
  createJSONDeserializer
376
478
  } = await import('@solidjs/web/serialization/decode');
377
479
  const deserializeChunk = createJSONDeserializer(codecOptions);
378
480
  function interpretChunk(chunk) {
481
+ if (chunk.startsWith(ERROR_TRAILER_PREFIX)) {
482
+ throw errorFromTrailer(chunk);
483
+ }
379
484
  return deserializeChunk(JSON.parse(chunk));
380
485
  }
381
486
  reader.drain(interpretChunk).then(() => deserializeChunk.abort(new Error("Server function stream ended unexpectedly.")), error => deserializeChunk.abort(error));
@@ -439,7 +544,8 @@ function copyInitHeaders(init) {
439
544
  for (const cookie of init.getSetCookie()) headers.append("Set-Cookie", cookie);
440
545
  return headers;
441
546
  }
442
- const STUB_GAP_FILL_EXCLUDED = /*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, "Location"].map(header => header.toLowerCase()));
547
+ const STUB_GAP_FILL_EXCLUDED = /*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, REDIRECT_HEADER, "Location",
548
+ ...COMPOSED_BODY_FRAMING].map(header => header.toLowerCase()));
443
549
  function fillsStubGap(key, headers, response) {
444
550
  if (key === "set-cookie" || STUB_GAP_FILL_EXCLUDED.has(key)) return false;
445
551
  if (response.body === null && (key === "content-type" || key === "content-length")) return false;
@@ -455,24 +561,16 @@ function commitEventResponse(response, event = getRequestEvent()) {
455
561
  if (fillsStubGap(key, response.headers, response)) hasGaps = true;
456
562
  });
457
563
  if (!cookies.length && !hasGaps) return response;
458
- try {
459
- for (const cookie of cookies) response.headers.append("Set-Cookie", cookie);
460
- stub.headers.forEach((value, key) => {
461
- if (fillsStubGap(key, response.headers, response)) response.headers.set(key, value);
462
- });
463
- return response;
464
- } catch {
465
- const headers = copyInitHeaders(response.headers);
466
- for (const cookie of cookies) headers.append("Set-Cookie", cookie);
467
- stub.headers.forEach((value, key) => {
468
- if (fillsStubGap(key, headers, response)) headers.set(key, value);
469
- });
470
- return new Response(response.body, {
471
- status: response.status,
472
- statusText: response.statusText,
473
- headers
474
- });
475
- }
564
+ const headers = copyInitHeaders(response.headers);
565
+ for (const cookie of cookies) headers.append("Set-Cookie", cookie);
566
+ stub.headers.forEach((value, key) => {
567
+ if (fillsStubGap(key, headers, response)) headers.set(key, value);
568
+ });
569
+ return new Response(response.body, {
570
+ status: response.status,
571
+ statusText: response.statusText,
572
+ headers
573
+ });
476
574
  }
477
575
 
478
576
  function encodeInputValue(value) {
@@ -504,11 +602,35 @@ function encodeFlashCookie(url, result, input, thrown) {
504
602
  thrown: !!thrown,
505
603
  input: input.map(encodeInputValue)
506
604
  };
605
+ if (fitsCookie(payload)) return flashCookie(payload);
606
+ payload.truncated = true;
607
+ payload.input = [];
608
+ if (!fitsCookie(payload)) {
609
+ if (typeof payload.result === "string") {
610
+ let prefix = payload.result;
611
+ while (prefix.length > 0 && !fitsCookie({
612
+ ...payload,
613
+ result: prefix
614
+ })) {
615
+ prefix = prefix.slice(0, prefix.length >> 1);
616
+ }
617
+ payload.result = prefix.length > 0 ? prefix : true;
618
+ } else {
619
+ payload.result = true;
620
+ }
621
+ }
622
+ return flashCookie(payload);
623
+ }
624
+ function flashCookie(payload) {
507
625
  return serializeCookie(FLASH_COOKIE, JSON.stringify(payload), {
508
626
  secure: true,
509
627
  httpOnly: true
510
628
  });
511
629
  }
630
+ const COOKIE_PAIR_BUDGET = 4000;
631
+ function fitsCookie(payload) {
632
+ return FLASH_COOKIE.length + 1 + encodeURIComponent(JSON.stringify(payload)).length <= COOKIE_PAIR_BUDGET;
633
+ }
512
634
  function decodeFlashCookie(cookieHeader) {
513
635
  const match = parseCookieHeader(cookieHeader)[FLASH_COOKIE];
514
636
  if (!match) return;
@@ -516,12 +638,14 @@ function decodeFlashCookie(cookieHeader) {
516
638
  const payload = JSON.parse(match);
517
639
  if (!payload || !payload.result) return;
518
640
  const result = payload.error ? new Error(payload.result) : payload.result;
519
- return {
641
+ const submission = {
520
642
  input: Array.isArray(payload.input) ? payload.input.map(decodeInputValue) : [],
521
643
  url: payload.url,
522
644
  result: payload.thrown ? undefined : result,
523
645
  error: payload.thrown ? result : undefined
524
646
  };
647
+ if (payload.truncated) submission.truncated = true;
648
+ return submission;
525
649
  } catch (error) {
526
650
  console.error(error);
527
651
  }
@@ -536,7 +660,9 @@ const config = {
536
660
  transformDirectResult: undefined,
537
661
  handleNoJS: undefined,
538
662
  endpoint: "/_server",
539
- csrf: true
663
+ csrf: true,
664
+ bodySizeLimit: 1_048_576,
665
+ maxArguments: 1000
540
666
  };
541
667
  function configureServerFunctionsServer({
542
668
  provideEvent,
@@ -548,7 +674,9 @@ function configureServerFunctionsServer({
548
674
  handleNoJS,
549
675
  endpoint,
550
676
  csrf,
551
- codec
677
+ codec,
678
+ bodySizeLimit,
679
+ maxArguments
552
680
  } = {}) {
553
681
  if (provideEvent !== undefined) config.provideEvent = provideEvent;
554
682
  if (wrapInvocation !== undefined) config.wrapInvocation = wrapInvocation;
@@ -560,6 +688,16 @@ function configureServerFunctionsServer({
560
688
  if (endpoint !== undefined) config.endpoint = endpoint;
561
689
  if (csrf !== undefined) config.csrf = csrf;
562
690
  if (codec !== undefined) configureServerFunctionsCodec(codec);
691
+ if (bodySizeLimit !== undefined) config.bodySizeLimit = bodySizeLimit;
692
+ if (maxArguments !== undefined) config.maxArguments = maxArguments;
693
+ }
694
+ const flightSources = new Map();
695
+ function registerFlightDataSource(source, hook) {
696
+ assertFlightSource(source);
697
+ flightSources.set(source, hook);
698
+ return () => {
699
+ if (flightSources.get(source) === hook) flightSources.delete(source);
700
+ };
563
701
  }
564
702
  function provideEvent(event, fn) {
565
703
  if (config.provideEvent) return config.provideEvent(event, fn);
@@ -567,6 +705,52 @@ function provideEvent(event, fn) {
567
705
  if (ctx) return ctx.run(event, fn);
568
706
  throw new Error("No request event provider. Configure one with configureServerFunctionsServer({ provideEvent }).");
569
707
  }
708
+ function scopeDeferredResult(value, scope) {
709
+ if (value === null || typeof value !== "object" && typeof value !== "function") return value;
710
+ const promised = scope(() => nativePromise(value));
711
+ if (promised) {
712
+ return promised.then(result => scope(() => scopeDeferredResult(result, scope)));
713
+ }
714
+ if (typeof ReadableStream !== "undefined" && value instanceof ReadableStream) {
715
+ let reader;
716
+ return new ReadableStream({
717
+ async pull(controller) {
718
+ try {
719
+ const step = await scope(() => {
720
+ if (!reader) reader = value.getReader();
721
+ return reader.read();
722
+ });
723
+ if (step.done) controller.close();else controller.enqueue(step.value);
724
+ } catch (error) {
725
+ controller.error(error);
726
+ }
727
+ },
728
+ cancel(reason) {
729
+ return scope(() => reader ? reader.cancel(reason) : value.cancel(reason));
730
+ }
731
+ }, {
732
+ highWaterMark: 0
733
+ });
734
+ }
735
+ const scopedIterator = symbol => ({
736
+ [symbol]() {
737
+ const iterator = scope(() => value[symbol]());
738
+ return new Proxy(iterator, {
739
+ get(target, property) {
740
+ const member = Reflect.get(target, property, target);
741
+ return typeof member === "function" && (property === "next" || property === "return" || property === "throw") ? (...args) => scope(() => member.apply(target, args)) : member;
742
+ }
743
+ });
744
+ }
745
+ });
746
+ if (typeof value[Symbol.asyncIterator] === "function") {
747
+ return scopedIterator(Symbol.asyncIterator);
748
+ }
749
+ if (typeof value[Symbol.iterator] === "function" && !Array.isArray(value) && !(value instanceof Map) && !(value instanceof Set) && !ArrayBuffer.isView(value)) {
750
+ return scopedIterator(Symbol.iterator);
751
+ }
752
+ return value;
753
+ }
570
754
  const REGISTRATIONS = new Map();
571
755
  const METHODS = new Map();
572
756
  const INVOCATIONS = new WeakMap();
@@ -581,6 +765,7 @@ function provideRPC() {
581
765
  }
582
766
  function registerServerFunction(id, callback) {
583
767
  provideRPC();
768
+ if (REGISTRATIONS.get(id) !== callback) METHODS.delete(id);
584
769
  REGISTRATIONS.set(id, callback);
585
770
  return callback;
586
771
  }
@@ -654,13 +839,17 @@ function createServerReference({
654
839
  const ogEvt = getRequestEvent();
655
840
  if (!ogEvt) throw new Error("Cannot call server function outside of a request");
656
841
  const evt = {
657
- ...ogEvt
842
+ ...ogEvt,
843
+ locals: {
844
+ ...ogEvt.locals
845
+ }
658
846
  };
659
847
  INVOCATIONS.set(evt, {
660
848
  id
661
849
  });
662
850
  evt.serverOnly = true;
663
- const result = provideEvent(evt, () => {
851
+ const scope = run => provideEvent(evt, run);
852
+ let result = provideEvent(evt, () => {
664
853
  const run = () => fn.apply(thisArg, args);
665
854
  return config.wrapInvocation ? config.wrapInvocation(run, {
666
855
  id,
@@ -669,19 +858,20 @@ function createServerReference({
669
858
  direct: true
670
859
  }) : run();
671
860
  });
861
+ result = scopeDeferredResult(result, scope);
672
862
  const transform = config.transformDirectResult;
673
863
  if (transform && result && typeof result.then === "function") {
674
- return result.then(value => transform(value, {
864
+ return result.then(value => scopeDeferredResult(transform(value, {
675
865
  id,
676
866
  args,
677
867
  event: evt
678
- }));
868
+ }), scope));
679
869
  }
680
- return transform ? transform(result, {
870
+ return transform ? scopeDeferredResult(transform(result, {
681
871
  id,
682
872
  args,
683
873
  event: evt
684
- }) : result;
874
+ }), scope) : result;
685
875
  }
686
876
  });
687
877
  return proxy;
@@ -725,18 +915,107 @@ function getServerFunctionInvocation() {
725
915
  function getEventServerFunctionInvocation(event) {
726
916
  return event && INVOCATIONS.get(event);
727
917
  }
728
- function resolveFunctionId(url) {
918
+ function resolveAddress(url) {
729
919
  return parseServerFunctionAddress(url.pathname, config.endpoint);
730
920
  }
731
- async function parseArguments(request, url, instance, codec) {
921
+ const DECODE_DEPTH_LIMIT = 64;
922
+ function assertDecodeDepth(value) {
923
+ let level = [value];
924
+ for (let depth = 0; level.length > 0; depth++) {
925
+ if (depth > DECODE_DEPTH_LIMIT) {
926
+ throw new TypeError("Server function arguments exceed the decode depth limit");
927
+ }
928
+ const next = [];
929
+ for (const node of level) {
930
+ if (node === null || typeof node !== "object") continue;
931
+ if (Array.isArray(node)) {
932
+ for (const child of node) next.push(child);
933
+ } else {
934
+ for (const key of Object.keys(node)) next.push(node[key]);
935
+ }
936
+ }
937
+ level = next;
938
+ }
939
+ }
940
+ const UNSAFE_ARGUMENT_KEYS = ["__proto__", "constructor", "prototype"];
941
+ function stripUnsafeArgumentKeys(value) {
942
+ const stack = [value];
943
+ const seen = new Set();
944
+ while (stack.length) {
945
+ const v = stack.pop();
946
+ if (v === null || typeof v !== "object" || seen.has(v)) continue;
947
+ seen.add(v);
948
+ for (const key of UNSAFE_ARGUMENT_KEYS) {
949
+ delete v[key];
950
+ }
951
+ for (const key of Object.keys(v)) stack.push(v[key]);
952
+ if (v instanceof Map) {
953
+ for (const [k, entry] of v) stack.push(k, entry);
954
+ } else if (v instanceof Set) {
955
+ for (const member of v) stack.push(member);
956
+ }
957
+ }
958
+ return value;
959
+ }
960
+ async function bufferBodyWithin(request, limit) {
961
+ const reader = request.body.getReader();
962
+ const signal = request.signal;
963
+ const chunks = [];
964
+ let total = 0;
965
+ const onAbort = () => {
966
+ reader.cancel(signal.reason).catch(() => {});
967
+ };
968
+ if (signal.aborted) onAbort();else signal.addEventListener("abort", onAbort, {
969
+ once: true
970
+ });
971
+ try {
972
+ for (;;) {
973
+ const {
974
+ done,
975
+ value
976
+ } = await reader.read();
977
+ if (signal.aborted) throw signal.reason;
978
+ if (done) break;
979
+ total += value.byteLength;
980
+ if (total > limit) {
981
+ reader.cancel().catch(() => {});
982
+ return null;
983
+ }
984
+ chunks.push(value);
985
+ }
986
+ } catch (error) {
987
+ reader.cancel(error).catch(() => {});
988
+ throw error;
989
+ } finally {
990
+ signal.removeEventListener("abort", onAbort);
991
+ reader.releaseLock();
992
+ }
993
+ const body = new Uint8Array(total);
994
+ let offset = 0;
995
+ for (const chunk of chunks) {
996
+ body.set(chunk, offset);
997
+ offset += chunk.byteLength;
998
+ }
999
+ return new Request(request, {
1000
+ body
1001
+ });
1002
+ }
1003
+ async function parseArguments(request, url, scripted, codec) {
732
1004
  const parsed = [];
733
1005
  const bodyFormat = request.method === "POST" ? request.headers.get(BODY_FORMAT_HEADER) : null;
734
1006
  const args = url.searchParams.get("args");
735
- if (args && (!instance || request.method === "GET" || bodyFormat !== BodyFormat.Serialized)) {
736
- const result = args.startsWith(";0x") ? await deserializeString(args, codec) : JSON.parse(args);
1007
+ if (args && (!scripted || request.method === "GET" || bodyFormat !== BodyFormat.Serialized)) {
1008
+ let result;
1009
+ if (args.startsWith(";0x")) {
1010
+ result = await deserializeString(args, codec);
1011
+ } else {
1012
+ result = JSON.parse(args);
1013
+ assertDecodeDepth(result);
1014
+ }
737
1015
  if (!Array.isArray(result)) {
738
1016
  throw new TypeError("Server function arguments must encode an array");
739
1017
  }
1018
+ stripUnsafeArgumentKeys(result);
740
1019
  for (const arg of result) {
741
1020
  parsed.push(arg);
742
1021
  }
@@ -746,18 +1025,37 @@ async function parseArguments(request, url, instance, codec) {
746
1025
  if (request.method === "POST" && request.body !== null) {
747
1026
  const decoded = await extractBody(request.clone(), codec);
748
1027
  if (bodyFormat === BodyFormat.Serialized || bodyFormat === BodyFormat.Json) {
749
- return decoded;
1028
+ if (bodyFormat === BodyFormat.Json) assertDecodeDepth(decoded);
1029
+ if (!Array.isArray(decoded)) {
1030
+ throw new TypeError("Server function arguments must encode an array");
1031
+ }
1032
+ return stripUnsafeArgumentKeys(decoded);
1033
+ }
1034
+ if (decoded === undefined) {
1035
+ if (bodyFormat === null && (await request.clone().arrayBuffer()).byteLength === 0) {
1036
+ return parsed;
1037
+ }
1038
+ throw new TypeError("Server function body carries no usable encoding");
750
1039
  }
751
1040
  parsed.push(decoded);
752
1041
  }
753
1042
  return parsed;
754
1043
  }
755
- async function foldFlightData(hook, event, headers, outcome, context = {}) {
1044
+ async function foldFlightData(hooks, event, headers, outcome, context = {}) {
756
1045
  if (outcome.value instanceof Response && outcome.value.body) return outcome.value;
757
1046
  digestOutcome(event, outcome);
758
- const data = await hook(event, outcome);
759
- if (data === undefined) return outcome.value;
760
- headers.set(SINGLE_FLIGHT_HEADER, "true");
1047
+ const folded = [];
1048
+ for (const [source, hook] of hooks) {
1049
+ try {
1050
+ const slice = await hook(event, outcome);
1051
+ if (slice !== undefined) folded.push([source, slice]);
1052
+ } catch (error) {
1053
+ console.error(`Error collecting flight data for source "${source}"`, error);
1054
+ }
1055
+ }
1056
+ if (folded.length === 0) return outcome.value;
1057
+ const data = Object.fromEntries(folded);
1058
+ headers.set(SINGLE_FLIGHT_HEADER, folded.map(([source]) => source).join(","));
761
1059
  if (context.transformFlightResult) {
762
1060
  const transformed = await context.transformFlightResult(event, {
763
1061
  value: outcome.value,
@@ -837,7 +1135,7 @@ function foldSetCookies(headers, setCookies) {
837
1135
  }
838
1136
  function mergeResponseHeaders(target, source) {
839
1137
  source.forEach((value, key) => {
840
- if (key !== "set-cookie") target.append(key, value);
1138
+ if (key !== "set-cookie" && !COMPOSED_BODY_FRAMING.has(key)) target.append(key, value);
841
1139
  });
842
1140
  if (source.getSetCookie) {
843
1141
  for (const cookie of source.getSetCookie()) target.append("Set-Cookie", cookie);
@@ -846,6 +1144,48 @@ function mergeResponseHeaders(target, source) {
846
1144
  }
847
1145
  }
848
1146
  const validRedirectStatuses = new Set([301, 302, 303, 307, 308]);
1147
+ function maskRedirect(headers, response, requestUrl) {
1148
+ const target = response.headers && response.headers.get("Location");
1149
+ if (target) {
1150
+ headers.set(REDIRECT_HEADER, `${response.status} ${new URL(target, requestUrl)}`);
1151
+ }
1152
+ headers.delete("Location");
1153
+ }
1154
+ const BOUNDED_COMPOSED_HEADERS = [REDIRECT_HEADER, "Location", REVALIDATE_HEADER];
1155
+ function enforceComposedHeaderInvariants(response) {
1156
+ for (const name of BOUNDED_COMPOSED_HEADERS) {
1157
+ const value = response.headers.get(name);
1158
+ if (value === null) continue;
1159
+ if (value.length > RESPONSE_HEADER_VALUE_LIMIT) {
1160
+ return refuseComposedHeader(response, name, `${name} response header refused at ${value.length} characters`, DEV ? `The ${name} response header is ${value.length} characters; past ` + `${RESPONSE_HEADER_VALUE_LIMIT} it would overflow receivers (an 8 KiB proxy ` + `buffer holds the whole header block) and the response dies at the socket after ` + `the mutation committed. Refused rather than trimmed: a cut redirect target is a ` + `different address, a dropped revalidate key is a silently stale cache. The ` + `redirect()/reload() helpers enforce this bound with the full reasoning at the ` + `call site.` : null);
1161
+ }
1162
+ if (name === REVALIDATE_HEADER) continue;
1163
+ const target = name === REDIRECT_HEADER ? value.slice(value.indexOf(" ") + 1) : value;
1164
+ if (!isHttpNavigationTarget(target)) {
1165
+ return refuseComposedHeader(response, name, `${name} response header refused: non-http(s) navigation target`, DEV ? `The ${name} response header carries a navigation target with a non-http(s) ` + `scheme ("${target.slice(0, 64)}"). A javascript: target is same-origin script ` + `execution in any integration that navigates to it, so only http(s) and ` + `relative targets leave this transport. If the target came from request data ` + `(?next= and friends), validate it against your own origin before redirecting.` : null);
1166
+ }
1167
+ }
1168
+ return response;
1169
+ }
1170
+ function refuseComposedHeader(response, name, headerMessage, body) {
1171
+ if (response.body) {
1172
+ try {
1173
+ const cancelled = response.body.cancel();
1174
+ if (cancelled && typeof cancelled.then === "function") cancelled.then(undefined, () => {});
1175
+ } catch {}
1176
+ }
1177
+ const headers = new Headers();
1178
+ headers.set(ERROR_HEADER, boundedErrorHeaderValue(DEV ? headerMessage : GENERIC_SERVER_ERROR_MESSAGE));
1179
+ return new Response(body, {
1180
+ status: 500,
1181
+ headers
1182
+ });
1183
+ }
1184
+ function warnScripted304(functionId) {
1185
+ if (DEV) {
1186
+ console.warn(`Server function "${functionId}" answered a scripted call with 304 Not Modified. ` + `The client transport sends no conditional headers, so nothing was asked to be ` + `revalidated: the call resolves to undefined, not "unchanged". For conditional ` + `reads, declare the function GET and set ETag/Cache-Control response headers - ` + `the browser owns that exchange and replays its cached answer on a 304.`);
1187
+ }
1188
+ }
849
1189
  function createNoJSHandler({
850
1190
  base = ""
851
1191
  } = {}) {
@@ -889,44 +1229,291 @@ function isFormPost(request) {
889
1229
  const type = request.headers.get("content-type") || "";
890
1230
  return type.startsWith("application/x-www-form-urlencoded") || type.startsWith("multipart/form-data");
891
1231
  }
892
- function serializeResponseStream(value, codecOptions, signal) {
893
- let closeIterator = null;
894
- let closed = false;
895
- let cancelSerialize = null;
896
- let onAbort = null;
897
- const teardown = () => {
898
- if (closed) return;
899
- closed = true;
900
- if (onAbort) signal.removeEventListener("abort", onAbort);
901
- if (cancelSerialize) cancelSerialize();
902
- if (closeIterator) closeIterator();
1232
+ function guardFailures(value, state) {
1233
+ if (!state) state = {
1234
+ seen: new WeakMap(),
1235
+ cyclic: new WeakSet()
903
1236
  };
904
- if (value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function") {
1237
+ const entered = enterGuard(value, state);
1238
+ if (!(entered instanceof Frame)) return entered;
1239
+ const stack = [entered];
1240
+ let delivered = NOTHING;
1241
+ for (;;) {
1242
+ const top = stack[stack.length - 1];
1243
+ const items = top.items;
1244
+ let pushed = null;
1245
+ while (top.i < items.length) {
1246
+ const i = top.i;
1247
+ let original;
1248
+ if (top.kind === OBJECT) {
1249
+ const descriptor = top.descriptors[items[i]];
1250
+ if ("value" in descriptor) {
1251
+ original = descriptor.value;
1252
+ } else if (typeof descriptor.get === "function") {
1253
+ if (top.accessorRead !== i) {
1254
+ try {
1255
+ top.accessorValue = descriptor.get.call(top.value);
1256
+ } catch (error) {
1257
+ throw sanitizeServerError(error);
1258
+ }
1259
+ top.accessorRead = i;
1260
+ }
1261
+ original = top.accessorValue;
1262
+ } else {
1263
+ top.i++;
1264
+ continue;
1265
+ }
1266
+ } else {
1267
+ original = items[i];
1268
+ }
1269
+ let guarded;
1270
+ if (delivered !== NOTHING) {
1271
+ guarded = delivered;
1272
+ delivered = NOTHING;
1273
+ } else {
1274
+ guarded = enterGuard(original, state);
1275
+ if (guarded instanceof Frame) {
1276
+ pushed = guarded;
1277
+ break;
1278
+ }
1279
+ }
1280
+ if (top.kind === ARRAY) {
1281
+ if (guarded !== original) {
1282
+ top.next[i] = guarded;
1283
+ top.changed = true;
1284
+ }
1285
+ } else if (top.kind === MAP) {
1286
+ if ((i & 1) === 0) top.pendingKey = guarded;else top.next.set(top.pendingKey, guarded);
1287
+ if (guarded !== original) top.changed = true;
1288
+ } else if (top.kind === SET) {
1289
+ top.next.add(guarded);
1290
+ if (guarded !== original) top.changed = true;
1291
+ } else if (guarded !== original || top.accessorRead === i) {
1292
+ Object.defineProperty(top.next, items[i], {
1293
+ value: guarded,
1294
+ writable: true,
1295
+ configurable: true,
1296
+ enumerable: top.descriptors[items[i]].enumerable
1297
+ });
1298
+ top.changed = true;
1299
+ }
1300
+ top.i++;
1301
+ }
1302
+ if (pushed !== null) {
1303
+ stack.push(pushed);
1304
+ continue;
1305
+ }
1306
+ stack.pop();
1307
+ const out = keepGuarded(top.value, top.next, top.changed, state);
1308
+ if (stack.length === 0) return out;
1309
+ delivered = out;
1310
+ }
1311
+ }
1312
+ const NOTHING = Symbol();
1313
+ const ARRAY = 0;
1314
+ const MAP = 1;
1315
+ const SET = 2;
1316
+ const OBJECT = 3;
1317
+ class Frame {
1318
+ constructor(kind, value, next, items, descriptors) {
1319
+ this.kind = kind;
1320
+ this.value = value;
1321
+ this.next = next;
1322
+ this.items = items;
1323
+ this.descriptors = descriptors;
1324
+ this.i = 0;
1325
+ this.changed = false;
1326
+ this.accessorRead = -1;
1327
+ this.accessorValue = undefined;
1328
+ this.pendingKey = undefined;
1329
+ }
1330
+ }
1331
+ function guardOperation(state, run) {
1332
+ return state.scope ? state.scope(run) : run();
1333
+ }
1334
+ function enterGuard(value, state) {
1335
+ if (value === null || typeof value !== "object") return value;
1336
+ if (state.seen.has(value)) {
1337
+ state.cyclic.add(value);
1338
+ return state.seen.get(value);
1339
+ }
1340
+ if (typeof ReadableStream !== "undefined" && value instanceof ReadableStream) {
1341
+ let reader;
1342
+ const gate = state.gate;
1343
+ let finished = false;
1344
+ const close = () => {
1345
+ if (finished) return;
1346
+ finished = true;
1347
+ try {
1348
+ const cancelled = guardOperation(state, () => reader ? reader.cancel() : value.cancel());
1349
+ if (cancelled && typeof cancelled.then === "function") cancelled.then(undefined, () => {});
1350
+ } catch {}
1351
+ };
1352
+ const guardedStream = new ReadableStream({
1353
+ async pull(controller) {
1354
+ try {
1355
+ if (gate && !finished && !gate.wantsMore()) await gate.awaitDemand();
1356
+ if (finished) {
1357
+ controller.close();
1358
+ return;
1359
+ }
1360
+ if (!reader) reader = guardOperation(state, () => value.getReader());
1361
+ const {
1362
+ done,
1363
+ value: chunk
1364
+ } = await guardOperation(state, () => reader.read());
1365
+ done ? controller.close() : controller.enqueue(guardOperation(state, () => guardFailures(chunk, state)));
1366
+ } catch (error) {
1367
+ controller.error(guardOperation(state, () => sanitizeServerError(error)));
1368
+ }
1369
+ },
1370
+ cancel(reason) {
1371
+ finished = true;
1372
+ return guardOperation(state, () => reader ? reader.cancel(reason) : value.cancel(reason));
1373
+ }
1374
+ });
1375
+ if (gate) gate.onOpen(close);
1376
+ state.seen.set(value, guardedStream);
1377
+ return guardedStream;
1378
+ }
1379
+ if (typeof value.then === "function") {
1380
+ const guardedPromise = Promise.resolve(value).then(resolved => guardOperation(state, () => guardFailures(resolved, state)), error => {
1381
+ throw guardOperation(state, () => sanitizeServerError(error));
1382
+ });
1383
+ guardedPromise.catch(() => {});
1384
+ state.seen.set(value, guardedPromise);
1385
+ return guardedPromise;
1386
+ }
1387
+ if (typeof value[Symbol.asyncIterator] === "function") {
905
1388
  const source = value;
906
- value = {
1389
+ const gate = state.gate;
1390
+ const guardedIterable = {
907
1391
  [Symbol.asyncIterator]() {
908
- const it = source[Symbol.asyncIterator]();
1392
+ const iterator = guardOperation(state, () => source[Symbol.asyncIterator]());
909
1393
  let finished = false;
910
- closeIterator = () => {
1394
+ const close = () => {
911
1395
  if (finished) return;
912
1396
  finished = true;
913
1397
  try {
914
- const returned = it.return && it.return();
1398
+ const returned = iterator.return && guardOperation(state, () => iterator.return());
915
1399
  if (returned && typeof returned.then === "function") returned.then(undefined, () => {});
916
1400
  } catch {}
917
1401
  };
918
- if (closed) closeIterator();
1402
+ if (gate) gate.onOpen(close);
1403
+ const step = () => finished ? Promise.resolve({
1404
+ done: true,
1405
+ value: undefined
1406
+ }) : guardOperation(state, () => iterator.next()).then(step => {
1407
+ if (step.done) {
1408
+ finished = true;
1409
+ return step;
1410
+ }
1411
+ return {
1412
+ done: false,
1413
+ value: guardOperation(state, () => guardFailures(step.value, state))
1414
+ };
1415
+ }, error => {
1416
+ throw guardOperation(state, () => sanitizeServerError(error));
1417
+ });
919
1418
  return {
920
- next: () => finished ? Promise.resolve({
921
- done: true,
922
- value: undefined
923
- }) : it.next()
1419
+ next: () => finished || !gate || gate.wantsMore() ? step() : gate.awaitDemand().then(step),
1420
+ return: () => {
1421
+ close();
1422
+ return Promise.resolve({
1423
+ done: true,
1424
+ value: undefined
1425
+ });
1426
+ }
924
1427
  };
925
1428
  }
926
1429
  };
1430
+ state.seen.set(value, guardedIterable);
1431
+ return guardedIterable;
1432
+ }
1433
+ if (state.scope && typeof value[Symbol.iterator] === "function" && !Array.isArray(value) && !(value instanceof Map) && !(value instanceof Set) && !ArrayBuffer.isView(value)) {
1434
+ const scopedIterable = scopeDeferredResult(value, state.scope);
1435
+ state.seen.set(value, scopedIterable);
1436
+ return scopedIterable;
1437
+ }
1438
+ if (Array.isArray(value)) {
1439
+ const next = value.slice();
1440
+ state.seen.set(value, next);
1441
+ return new Frame(ARRAY, value, next, value, null);
1442
+ }
1443
+ if (value instanceof Map) {
1444
+ const next = new Map();
1445
+ state.seen.set(value, next);
1446
+ const items = [];
1447
+ for (const entry of value) items.push(entry[0], entry[1]);
1448
+ return new Frame(MAP, value, next, items, null);
1449
+ }
1450
+ if (value instanceof Set) {
1451
+ const next = new Set();
1452
+ state.seen.set(value, next);
1453
+ return new Frame(SET, value, next, [...value], null);
1454
+ }
1455
+ const prototype = Object.getPrototypeOf(value);
1456
+ if (prototype !== Object.prototype && prototype !== null) {
1457
+ state.seen.set(value, value);
1458
+ return value;
927
1459
  }
1460
+ const descriptors = Object.getOwnPropertyDescriptors(value);
1461
+ for (const key of Object.keys(descriptors)) {
1462
+ descriptors[key].configurable = true;
1463
+ if ("value" in descriptors[key]) descriptors[key].writable = true;
1464
+ }
1465
+ const next = Object.create(prototype, descriptors);
1466
+ state.seen.set(value, next);
1467
+ return new Frame(OBJECT, value, next, Object.keys(value), descriptors);
1468
+ }
1469
+ function keepGuarded(value, next, changed, state) {
1470
+ if (changed || state.cyclic.has(value)) return next;
1471
+ state.seen.set(value, value);
1472
+ return value;
1473
+ }
1474
+ function serializeResponseStream(value, codecOptions, signal, scope) {
1475
+ let closed = false;
1476
+ let streamController = null;
1477
+ let demandWaiters = null;
1478
+ const wantsMore = () => streamController !== null && streamController.desiredSize > 0;
1479
+ const awaitDemand = () => new Promise(resolve => (demandWaiters ??= []).push(resolve));
1480
+ const supplyDemand = () => {
1481
+ const resolvers = demandWaiters;
1482
+ demandWaiters = null;
1483
+ if (resolvers) for (const resolve of resolvers) resolve();
1484
+ };
1485
+ const sourceClosers = new Set();
1486
+ const gate = {
1487
+ wantsMore,
1488
+ awaitDemand,
1489
+ onOpen(close) {
1490
+ if (closed) close();else sourceClosers.add(close);
1491
+ }
1492
+ };
1493
+ const guardState = {
1494
+ seen: new WeakMap(),
1495
+ cyclic: new WeakSet(),
1496
+ gate,
1497
+ scope
1498
+ };
1499
+ value = guardOperation(guardState, () => guardFailures(value, guardState));
1500
+ let cancelSerialize = null;
1501
+ let onAbort = null;
1502
+ const finishSource = () => {
1503
+ for (const close of sourceClosers) close();
1504
+ sourceClosers.clear();
1505
+ supplyDemand();
1506
+ };
1507
+ const teardown = () => {
1508
+ if (closed) return;
1509
+ closed = true;
1510
+ if (onAbort) signal.removeEventListener("abort", onAbort);
1511
+ if (cancelSerialize) cancelSerialize();
1512
+ finishSource();
1513
+ };
928
1514
  return new ReadableStream({
929
1515
  async start(controller) {
1516
+ streamController = controller;
930
1517
  if (signal) {
931
1518
  if (signal.aborted) {
932
1519
  teardown();
@@ -962,29 +1549,54 @@ function serializeResponseStream(value, codecOptions, signal) {
962
1549
  if (closed) return;
963
1550
  closed = true;
964
1551
  if (onAbort) signal.removeEventListener("abort", onAbort);
1552
+ finishSource();
965
1553
  controller.close();
966
1554
  },
967
1555
  onError(error) {
968
1556
  if (closed) return;
969
1557
  closed = true;
970
1558
  if (onAbort) signal.removeEventListener("abort", onAbort);
971
- controller.error(error);
1559
+ finishSource();
1560
+ try {
1561
+ const delivered = sanitizeServerError(DEV && error instanceof Error ? new Error(`Server function result could not be encoded: ${error.message}`) : error);
1562
+ controller.enqueue(createChunk(encodeErrorTrailer(delivered)));
1563
+ controller.close();
1564
+ } catch {
1565
+ try {
1566
+ controller.error(error);
1567
+ } catch {}
1568
+ }
972
1569
  }
973
1570
  });
974
1571
  },
1572
+ pull() {
1573
+ supplyDemand();
1574
+ },
975
1575
  cancel() {
976
1576
  teardown();
977
1577
  }
978
1578
  });
979
1579
  }
980
- function serializedResponse(value, headers, codec, signal) {
1580
+ function serializedResponse(value, headers, codec, signal, scope) {
981
1581
  headers.set(BODY_FORMAT_HEADER, BodyFormat.Serialized);
982
1582
  headers.set("Content-Type", "text/plain");
983
- return new Response(serializeResponseStream(value, codec, signal), {
1583
+ return new Response(serializeResponseStream(value, codec, signal, scope), {
984
1584
  headers
985
1585
  });
986
1586
  }
987
- function encodeResult(value, headers, status, codec, signal) {
1587
+ function encodeResult(value, headers, status, codec, signal, scope) {
1588
+ if (NULL_BODY_STATUSES.has(status)) {
1589
+ if (value === undefined || value === null) {
1590
+ headers.set(BODY_FORMAT_HEADER, BodyFormat.Void);
1591
+ return new Response(null, {
1592
+ status,
1593
+ headers
1594
+ });
1595
+ }
1596
+ const error = new Error(`Server function answered status ${status}, which forbids a response body, with a value. ` + `Return respond(undefined, { status: ${status} }) for a bodiless answer, or drop the ` + `status to send the value.`);
1597
+ headers.set(ERROR_HEADER, encodeErrorHeaderValue(error.message));
1598
+ return encodeResult(error, headers, 500, codec, signal, scope);
1599
+ }
988
1600
  const direct = getHeadersAndBody(value);
989
1601
  if (direct) {
990
1602
  for (const [key, val] of Object.entries(direct.headers || {})) {
@@ -1003,21 +1615,37 @@ function encodeResult(value, headers, status, codec, signal) {
1003
1615
  });
1004
1616
  }
1005
1617
  try {
1006
- if (isJSONSafe(value)) {
1618
+ const jsonSafe = scope ? scope(() => isJSONSafe(value)) : isJSONSafe(value);
1619
+ if (jsonSafe) {
1007
1620
  headers.set(BODY_FORMAT_HEADER, BodyFormat.Json);
1008
1621
  headers.set("Content-Type", "application/json");
1009
- return new Response(JSON.stringify(value), {
1622
+ const body = scope ? scope(() => JSON.stringify(value)) : JSON.stringify(value);
1623
+ return new Response(body, {
1010
1624
  status,
1011
1625
  headers
1012
1626
  });
1013
1627
  }
1014
1628
  } catch {
1015
1629
  }
1016
- const response = serializedResponse(value, headers, codec, signal);
1017
- return status === 200 ? response : new Response(response.body, {
1018
- status,
1019
- headers
1020
- });
1630
+ try {
1631
+ const response = serializedResponse(value, headers, codec, signal, scope);
1632
+ return status === 200 ? response : new Response(response.body, {
1633
+ status,
1634
+ headers
1635
+ });
1636
+ } catch (error) {
1637
+ throw DEV && error instanceof Error ? new Error(`Server function result could not be encoded: ${error.message}`) : error;
1638
+ }
1639
+ }
1640
+ const ERROR_HEADER_VALUE_LIMIT = 1024;
1641
+ function boundedErrorHeaderValue(message) {
1642
+ let label = message.length > 256 ? message.slice(0, 256) : message;
1643
+ let encoded = encodeErrorHeaderValue(label);
1644
+ while (encoded.length > ERROR_HEADER_VALUE_LIMIT && label.length > 1) {
1645
+ label = label.slice(0, Math.ceil(label.length / 2));
1646
+ encoded = encodeErrorHeaderValue(label);
1647
+ }
1648
+ return encoded;
1021
1649
  }
1022
1650
  const GENERIC_SERVER_ERROR_MESSAGE = "Internal Server Error";
1023
1651
  let DEV = false === true;
@@ -1041,11 +1669,12 @@ function serverFunctionUrl(id, boundArgs) {
1041
1669
  return `${address}?args=${encodeURIComponent(JSON.stringify(boundArgs))}`;
1042
1670
  }
1043
1671
  function parseServerFunctionUrl(url) {
1044
- return parseServerFunctionAddress(new URL(url, "http://localhost").pathname, config.endpoint);
1672
+ const parsed = parseServerFunctionAddress(new URL(url, "http://localhost").pathname, config.endpoint);
1673
+ return parsed && parsed.id;
1045
1674
  }
1046
1675
  async function matchesOrigin(origin, request, matcher) {
1047
1676
  if (matcher === undefined) return origin === new URL(request.url).origin;
1048
- if (typeof matcher === "function") return !!(await matcher(origin, request));
1677
+ if (typeof matcher === "function") return (await matcher(origin, request)) === true;
1049
1678
  return Array.isArray(matcher) ? matcher.includes(origin) : origin === matcher;
1050
1679
  }
1051
1680
  async function allowsServerFunctionRequest(request, options) {
@@ -1097,14 +1726,37 @@ function forbiddenResponse() {
1097
1726
  }
1098
1727
  }));
1099
1728
  }
1729
+ function nativePromise(value) {
1730
+ if (value instanceof Promise) return value;
1731
+ try {
1732
+ if (Object.prototype.toString.call(value) === "[object Promise]") return Promise.prototype.then.call(value, value => value);
1733
+ } catch {}
1734
+ }
1100
1735
  async function handleServerFunctionRequest(request, options = {}) {
1101
- const codec = options.codec !== undefined ? options.codec : getServerFunctionsCodec();
1736
+ const codec = {
1737
+ ...(options.codec !== undefined ? options.codec : getServerFunctionsCodec())
1738
+ };
1739
+ codec.serializeErrorStacks ??= DEV;
1102
1740
  const url = new URL(request.url);
1103
1741
  const method = request.method;
1104
- const functionId = resolveFunctionId(url);
1742
+ const address = resolveAddress(url);
1743
+ const functionId = address && address.id;
1105
1744
  const declaredRead = (method === "GET" || method === "HEAD") && functionId !== null && METHODS.get(functionId) === "GET";
1106
1745
  const csrf = options.csrf !== undefined ? options.csrf : config.csrf;
1107
- const protectsRequest = csrf !== false && !declaredRead;
1746
+ const protectsRequest = csrf !== false && (!declaredRead || typeof csrf === "object" && csrf.protectDeclaredReads === true);
1747
+ let serverFunction;
1748
+ if (functionId) {
1749
+ try {
1750
+ serverFunction = getServerFunction(functionId);
1751
+ } catch {
1752
+ return finalizeTransportResponse(new Response(DEV ? `Unknown server function: ${functionId}` : null, {
1753
+ status: 404,
1754
+ headers: {
1755
+ [UNKNOWN_HEADER]: "true"
1756
+ }
1757
+ }), method);
1758
+ }
1759
+ }
1108
1760
  if (protectsRequest && !(await allowsServerFunctionRequest(request, csrf === true ? {} : csrf))) {
1109
1761
  return finalizeTransportResponse(forbiddenResponse(), method);
1110
1762
  }
@@ -1115,15 +1767,7 @@ async function handleServerFunctionRequest(request, options = {}) {
1115
1767
  });
1116
1768
  return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1117
1769
  }
1118
- let serverFunction;
1119
- try {
1120
- serverFunction = getServerFunction(functionId);
1121
- } catch {
1122
- const response = new Response(DEV ? `Unknown server function: ${functionId}` : null, {
1123
- status: 404
1124
- });
1125
- return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1126
- }
1770
+ const scripted = address.data;
1127
1771
  if (method !== "POST" && !declaredRead) {
1128
1772
  const response = new Response(DEV ? `Method not allowed for server function: ${functionId}` : null, {
1129
1773
  status: 405,
@@ -1133,25 +1777,103 @@ async function handleServerFunctionRequest(request, options = {}) {
1133
1777
  });
1134
1778
  return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1135
1779
  }
1136
- const event = options.createEvent ? options.createEvent(request) : {
1137
- request,
1138
- locals: {}
1780
+ const bodySizeLimit = options.bodySizeLimit !== undefined ? options.bodySizeLimit : config.bodySizeLimit;
1781
+ const argsEncoding = url.searchParams.get("args");
1782
+ if (argsEncoding !== null && argsEncoding.length > bodySizeLimit) {
1783
+ const response = new Response(DEV ? "Server function arguments exceed the configured bodySizeLimit" : null, {
1784
+ status: 413
1785
+ });
1786
+ return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1787
+ }
1788
+ if (method === "POST" && request.body !== null && bodySizeLimit !== Infinity) {
1789
+ const raw = request.headers.get("content-length");
1790
+ const declared = raw !== null && /^\d+$/.test(raw) ? Number(raw) : NaN;
1791
+ if (declared > bodySizeLimit) {
1792
+ const response = new Response(DEV ? "Server function request body exceeds the configured bodySizeLimit" : null, {
1793
+ status: 413
1794
+ });
1795
+ return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1796
+ }
1797
+ if (!(declared > 0)) {
1798
+ let bounded;
1799
+ try {
1800
+ bounded = await bufferBodyWithin(request, bodySizeLimit);
1801
+ } catch {
1802
+ const response = new Response(DEV ? "Malformed server function arguments" : null, {
1803
+ status: 400
1804
+ });
1805
+ return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1806
+ }
1807
+ if (bounded === null) {
1808
+ const response = new Response(DEV ? "Server function request body exceeds the configured bodySizeLimit" : null, {
1809
+ status: 413
1810
+ });
1811
+ return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1812
+ }
1813
+ request = bounded;
1814
+ }
1815
+ }
1816
+ let event;
1817
+ try {
1818
+ event = options.createEvent ? options.createEvent(request) : {
1819
+ request,
1820
+ locals: {}
1821
+ };
1822
+ const promised = nativePromise(event);
1823
+ if (promised) event = await promised;
1824
+ } catch (error) {
1825
+ const safe = sanitizeServerError(error);
1826
+ const message = safe instanceof Error ? safe.message : String(safe);
1827
+ const headers = new Headers();
1828
+ headers.set(ERROR_HEADER, boundedErrorHeaderValue(message));
1829
+ const response = scripted ? encodeResult(safe, headers, 500, codec, request.signal) : new Response(DEV ? message : null, {
1830
+ status: 500
1831
+ });
1832
+ return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1833
+ }
1834
+ const refuseCommitted = raw => {
1835
+ const response = commitEventResponse(raw, event);
1836
+ return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1139
1837
  };
1140
1838
  const provide = options.provideEvent || provideEvent;
1839
+ const scope = run => provide(event, run);
1141
1840
  const flightHook = options.collectFlightData !== undefined ? options.collectFlightData : config.collectFlightData;
1142
1841
  const transformResult = options.transformResult !== undefined ? options.transformResult : config.transformResult;
1143
1842
  const wrapInvocation = options.wrapInvocation !== undefined ? options.wrapInvocation : config.wrapInvocation;
1144
1843
  const transformFlightResult = options.transformFlightResult !== undefined ? options.transformFlightResult : config.transformFlightResult;
1145
- const handleNoJS = options.handleNoJS !== undefined ? options.handleNoJS : config.handleNoJS !== undefined ? config.handleNoJS : isFormPost(request) ? defaultNoJSHandler || (defaultNoJSHandler = createNoJSHandler()) : undefined;
1146
- const collectsFlight = !!(flightHook && instance && request.headers.has(SINGLE_FLIGHT_HEADER));
1844
+ let handleNoJS = options.handleNoJS !== undefined ? options.handleNoJS : config.handleNoJS;
1845
+ if (handleNoJS === undefined && !scripted && isFormPost(request)) {
1846
+ const fetchMode = request.headers.get("Sec-Fetch-Mode");
1847
+ if (fetchMode === null || fetchMode === "navigate") {
1848
+ handleNoJS = defaultNoJSHandler || (defaultNoJSHandler = createNoJSHandler());
1849
+ } else {
1850
+ const response = new Response(DEV ? "The bare server-function address answers form navigations with the " + "no-JS redirect convention. Scripted callers use the data address " + `(…/data/${functionId}) or send the ${BODY_FORMAT_HEADER} tag.` : null, {
1851
+ status: 400
1852
+ });
1853
+ return refuseCommitted(response);
1854
+ }
1855
+ }
1856
+ const flightHeader = scripted && method === "POST" ? request.headers.get(SINGLE_FLIGHT_HEADER) : null;
1857
+ const flightHooks = flightHeader ? flightHeader.split(",").flatMap(source => {
1858
+ const hook = source === "true" ? flightHook : flightSources.get(source);
1859
+ return hook ? [[source, hook]] : [];
1860
+ }) : [];
1861
+ const collectsFlight = flightHooks.length > 0;
1147
1862
  let parsed;
1148
1863
  try {
1149
- parsed = await parseArguments(request, url, instance, codec);
1864
+ parsed = await parseArguments(request, url, scripted, codec);
1150
1865
  } catch {
1151
1866
  const response = new Response(DEV ? "Malformed server function arguments" : null, {
1152
1867
  status: 400
1153
1868
  });
1154
- return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1869
+ return refuseCommitted(response);
1870
+ }
1871
+ const maxArguments = options.maxArguments !== undefined ? options.maxArguments : config.maxArguments;
1872
+ if (parsed.length > maxArguments) {
1873
+ const response = new Response(DEV ? "Server function call exceeds the configured maxArguments" : null, {
1874
+ status: 400
1875
+ });
1876
+ return refuseCommitted(response);
1155
1877
  }
1156
1878
  const flightContext = {
1157
1879
  id: functionId,
@@ -1165,7 +1887,8 @@ async function handleServerFunctionRequest(request, options = {}) {
1165
1887
  const headers = new Headers();
1166
1888
  const dispatch = async () => {
1167
1889
  try {
1168
- let result = await provide(event, async () => {
1890
+ let invocations = 0;
1891
+ const invokeOnce = async () => {
1169
1892
  INVOCATIONS.set(event, {
1170
1893
  id: functionId
1171
1894
  });
@@ -1177,7 +1900,16 @@ async function handleServerFunctionRequest(request, options = {}) {
1177
1900
  request,
1178
1901
  direct: false
1179
1902
  }) : run();
1903
+ };
1904
+ let result = await provide(event, () => {
1905
+ if (++invocations > 1) {
1906
+ throw new Error("provideEvent invoked the server function callback more than once: a second " + "invocation would commit the call's side effects twice. The hook must call " + "fn exactly once and return its result.");
1907
+ }
1908
+ return invokeOnce();
1180
1909
  });
1910
+ if (invocations !== 1) {
1911
+ throw new Error(invocations === 0 ? "provideEvent returned without invoking the server function callback: the call " + "would have answered as a void success without running the function. The hook " + "must call fn exactly once and return its result." : "provideEvent invoked the server function callback more than once: a second " + "invocation would commit the call's side effects twice. The hook must call " + "fn exactly once and return its result.");
1912
+ }
1181
1913
  if (transformResult) {
1182
1914
  result = await transformResult(event, result, flightContext);
1183
1915
  }
@@ -1188,25 +1920,29 @@ async function handleServerFunctionRequest(request, options = {}) {
1188
1920
  response,
1189
1921
  value
1190
1922
  } = result;
1191
- if (!instance && !handleNoJS && response && response.body) {
1923
+ if (!scripted && !handleNoJS && response && response.body) {
1192
1924
  return response;
1193
1925
  }
1194
1926
  if (response && response.headers) {
1195
1927
  mergeResponseHeaders(headers, response.headers);
1196
1928
  }
1197
- if (response && response.status && (response.status < 300 || response.status >= 400)) {
1929
+ if (response && response.status && (!scripted || !validRedirectStatuses.has(response.status))) {
1198
1930
  status = response.status;
1931
+ } else if (response && response.status) {
1932
+ maskRedirect(headers, response, request.url);
1199
1933
  }
1200
1934
  metadata = response;
1201
1935
  result = value;
1202
1936
  } else if (result instanceof Response) {
1203
1937
  if (result.headers && result.headers.has("X-Content-Raw")) return result;
1204
- if (instance) {
1938
+ if (scripted) {
1205
1939
  if (result.headers) {
1206
1940
  mergeResponseHeaders(headers, result.headers);
1207
1941
  }
1208
- if (result.status && (result.status < 300 || result.status >= 400)) {
1942
+ if (result.status && !validRedirectStatuses.has(result.status)) {
1209
1943
  status = result.status;
1944
+ } else if (result.status) {
1945
+ maskRedirect(headers, result, request.url);
1210
1946
  }
1211
1947
  metadata = result;
1212
1948
  if (result.body == null) {
@@ -1215,7 +1951,7 @@ async function handleServerFunctionRequest(request, options = {}) {
1215
1951
  }
1216
1952
  }
1217
1953
  if (collectsFlight) {
1218
- result = await foldFlightData(flightHook, event, headers, {
1954
+ result = await foldFlightData(flightHooks, event, headers, {
1219
1955
  id: functionId,
1220
1956
  value: result,
1221
1957
  response: metadata,
@@ -1224,19 +1960,37 @@ async function handleServerFunctionRequest(request, options = {}) {
1224
1960
  }, flightContext);
1225
1961
  if (result instanceof Response && result.headers.has("X-Content-Raw")) return result;
1226
1962
  }
1227
- if (!instance) {
1228
- if (handleNoJS) return handleNoJS(result, request, parsed);
1963
+ if (!scripted) {
1964
+ if (handleNoJS) return handleNoJS(result ?? metadata, request, parsed);
1229
1965
  if (result instanceof Response) return result;
1230
- return encodeResult(result, headers, 200, codec, request.signal);
1966
+ return encodeResult(result, headers, status, codec, request.signal, scope);
1231
1967
  }
1232
- return encodeResult(result, headers, status, codec, request.signal);
1968
+ if (status === 304) warnScripted304(functionId);
1969
+ return encodeResult(result, headers, status, codec, request.signal, scope);
1233
1970
  } catch (x) {
1971
+ const respondThrown = value => {
1972
+ const safe = sanitizeServerError(value);
1973
+ if (!scripted) {
1974
+ if (handleNoJS) return handleNoJS(safe, request, parsed, true);
1975
+ const message = safe instanceof Error ? safe.message : String(safe);
1976
+ return new Response(DEV ? message : null, {
1977
+ status: 500
1978
+ });
1979
+ }
1980
+ const error = safe instanceof Error ? safe.message : typeof safe === "string" ? safe : "true";
1981
+ headers.set(ERROR_HEADER, boundedErrorHeaderValue(error));
1982
+ return encodeResult(safe, headers, 500, codec, request.signal, scope);
1983
+ };
1234
1984
  if (x instanceof Response || isResponseEnvelope(x)) {
1235
1985
  if (transformResult) {
1236
- x = await transformResult(event, x, {
1237
- ...flightContext,
1238
- thrown: true
1239
- });
1986
+ try {
1987
+ x = await transformResult(event, x, {
1988
+ ...flightContext,
1989
+ thrown: true
1990
+ });
1991
+ } catch (hookError) {
1992
+ return respondThrown(hookError);
1993
+ }
1240
1994
  }
1241
1995
  let status = 200;
1242
1996
  let metadata;
@@ -1248,8 +2002,10 @@ async function handleServerFunctionRequest(request, options = {}) {
1248
2002
  if (response && response.headers) {
1249
2003
  mergeResponseHeaders(headers, response.headers);
1250
2004
  }
1251
- if (response && response.status && (!instance || response.status < 300 || response.status >= 400)) {
2005
+ if (response && response.status && (!scripted || !validRedirectStatuses.has(response.status))) {
1252
2006
  status = response.status;
2007
+ } else if (response && response.status) {
2008
+ maskRedirect(headers, response, request.url);
1253
2009
  }
1254
2010
  metadata = response;
1255
2011
  x = value;
@@ -1257,8 +2013,10 @@ async function handleServerFunctionRequest(request, options = {}) {
1257
2013
  if (x.headers) {
1258
2014
  mergeResponseHeaders(headers, x.headers);
1259
2015
  }
1260
- if (x.status && (!instance || x.status < 300 || x.status >= 400)) {
2016
+ if (x.status && (!scripted || !validRedirectStatuses.has(x.status))) {
1261
2017
  status = x.status;
2018
+ } else if (x.status) {
2019
+ maskRedirect(headers, x, request.url);
1262
2020
  }
1263
2021
  metadata = x;
1264
2022
  if (x.body == null) {
@@ -1266,7 +2024,7 @@ async function handleServerFunctionRequest(request, options = {}) {
1266
2024
  }
1267
2025
  }
1268
2026
  if (collectsFlight) {
1269
- x = await foldFlightData(flightHook, event, headers, {
2027
+ x = await foldFlightData(flightHooks, event, headers, {
1270
2028
  id: functionId,
1271
2029
  value: x,
1272
2030
  response: metadata,
@@ -1274,38 +2032,38 @@ async function handleServerFunctionRequest(request, options = {}) {
1274
2032
  thrown: true
1275
2033
  }, flightContext);
1276
2034
  if (x instanceof Response && x.headers.has("X-Content-Raw")) {
2035
+ x = ownResponse(x);
1277
2036
  x.headers.set(ERROR_HEADER, "true");
1278
2037
  return x;
1279
2038
  }
1280
2039
  }
1281
2040
  headers.set(ERROR_HEADER, "true");
1282
- if (!instance) {
2041
+ if (!scripted) {
1283
2042
  if (handleNoJS) return handleNoJS(x ?? metadata, request, parsed, true);
1284
2043
  if (x instanceof Response) return x;
1285
2044
  }
1286
- return encodeResult(x, headers, status, codec, request.signal);
1287
- }
1288
- const safe = sanitizeServerError(x);
1289
- if (!instance) {
1290
- if (handleNoJS) return handleNoJS(safe, request, parsed, true);
1291
- const message = safe instanceof Error ? safe.message : String(safe);
1292
- return new Response(DEV ? message : null, {
1293
- status: 500
1294
- });
2045
+ if (scripted && status === 304) warnScripted304(functionId);
2046
+ return encodeResult(x, headers, status, codec, request.signal, scope);
1295
2047
  }
1296
- const error = safe instanceof Error ? safe.message : typeof safe === "string" ? safe : "true";
1297
- headers.set(ERROR_HEADER, encodeErrorHeaderValue(error));
1298
- return encodeResult(safe, headers, 200, codec, request.signal);
2048
+ return respondThrown(x);
1299
2049
  }
1300
2050
  };
1301
- const response = commitEventResponse(await dispatch(), event);
2051
+ const response = commitEventResponse(enforceComposedHeaderInvariants(ownResponse(await dispatch())), event);
1302
2052
  return finalizeTransportResponse(protectsRequest ? withCSRFVary(response) : response, method);
1303
2053
  }
2054
+ function ownResponse(response) {
2055
+ try {
2056
+ return new Response(response.body, response);
2057
+ } catch {
2058
+ return response;
2059
+ }
2060
+ }
1304
2061
  function finalizeTransportResponse(response, method) {
1305
2062
  const stripBody = method === "HEAD" && response.body !== null;
1306
- if (stripBody || !response.headers.has("Cache-Control")) {
2063
+ const defaultsCache = !response.headers.has("Cache-Control") && response.status !== 304;
2064
+ if (stripBody || defaultsCache) {
1307
2065
  try {
1308
- if (!response.headers.has("Cache-Control")) {
2066
+ if (defaultsCache) {
1309
2067
  response.headers.set("Cache-Control", "no-store");
1310
2068
  }
1311
2069
  if (!stripBody) return response;
@@ -1317,7 +2075,7 @@ function finalizeTransportResponse(response, method) {
1317
2075
  });
1318
2076
  } catch {
1319
2077
  const headers = new Headers(response.headers);
1320
- if (!headers.has("Cache-Control")) headers.set("Cache-Control", "no-store");
2078
+ if (defaultsCache && !headers.has("Cache-Control")) headers.set("Cache-Control", "no-store");
1321
2079
  if (stripBody) response.body.cancel().catch(() => {});
1322
2080
  return new Response(stripBody ? null : response.body, {
1323
2081
  status: response.status,
@@ -1329,4 +2087,4 @@ function finalizeTransportResponse(response, method) {
1329
2087
  return response;
1330
2088
  }
1331
2089
 
1332
- export { ERROR_HEADER, FLASH_COOKIE, GENERIC_SERVER_ERROR_MESSAGE, GET, INSTANCE_HEADER, SERVER_FUNCTION_INVOKE, SINGLE_FLIGHT_HEADER, clearFlashCookie, configureServerFunctionsServer, createNoJSHandler, createServerReference, decodeErrorHeaderValue, decodeFlashCookie, decodeResponse, decodeResponsePayload, encodeErrorHeaderValue, encodeFlashCookie, foldSetCookies, getEventServerFunctionInvocation, getServerFunction, getServerFunctionInvocation, getServerFunctionMetadata, handleServerFunctionRequest, hasFlashCookie, invoke, isServerFunction, live, observeServerFunctionCalls, parseServerFunctionUrl, registerServerFunction, registerServerReference, sanitizeServerError, serializeResponseStream, serverFunctionUrl, setServerFunctionsDev, subscribeFlightData, withMeta };
2090
+ export { ERROR_HEADER, FLASH_COOKIE, GENERIC_SERVER_ERROR_MESSAGE, GET, INSTANCE_HEADER, REDIRECT_HEADER, SERVER_FUNCTION_INVOKE, SINGLE_FLIGHT_HEADER, UNKNOWN_HEADER, clearFlashCookie, configureServerFunctionsServer, createNoJSHandler, createServerReference, decodeErrorHeaderValue, decodeFlashCookie, decodeRedirectHeaderValue, decodeResponse, decodeResponsePayload, encodeErrorHeaderValue, encodeFlashCookie, foldSetCookies, getEventServerFunctionInvocation, getServerFunction, getServerFunctionInvocation, getServerFunctionMetadata, guardFailures, handleServerFunctionRequest, hasFlashCookie, invoke, isServerFunction, live, observeServerFunctionCalls, parseServerFunctionUrl, registerFlightDataSource, registerServerFunction, registerServerReference, sanitizeServerError, serializeResponseStream, serverFunctionUrl, setServerFunctionsDev, subscribeFlightData, withMeta };