@solidjs/web 2.0.0-beta.32 → 2.0.0-beta.33

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 (52) hide show
  1. package/dist/dev.cjs +51 -15
  2. package/dist/dev.js +47 -16
  3. package/dist/server.cjs +710 -71
  4. package/dist/server.js +707 -74
  5. package/dist/web.cjs +51 -15
  6. package/dist/web.js +47 -16
  7. package/frames/dist/client.cjs +181 -64
  8. package/frames/dist/client.dev.cjs +185 -64
  9. package/frames/dist/client.dev.js +183 -62
  10. package/frames/dist/client.js +179 -62
  11. package/frames/dist/server.cjs +969 -133
  12. package/frames/dist/server.js +971 -135
  13. package/package.json +17 -6
  14. package/serialization/decode/package.json +20 -0
  15. package/serialization/dist/decode.cjs +110 -0
  16. package/serialization/dist/decode.js +104 -0
  17. package/serialization/dist/serialization.cjs +98 -43
  18. package/serialization/dist/serialization.js +99 -44
  19. package/serialization/types/index.d.ts +18 -160
  20. package/serialization/types/serializer-decode.d.ts +182 -0
  21. package/serialization/types-cjs/index.d.cts +18 -160
  22. package/serialization/types-cjs/serializer-decode.d.cts +182 -0
  23. package/server-functions/dist/client.cjs +101 -105
  24. package/server-functions/dist/client.js +101 -105
  25. package/server-functions/dist/server.cjs +131 -107
  26. package/server-functions/dist/server.dev.cjs +131 -107
  27. package/server-functions/dist/server.dev.js +132 -108
  28. package/server-functions/dist/server.js +132 -108
  29. package/types/client.d.ts +23 -1
  30. package/types/cookies.d.ts +93 -0
  31. package/types/core.d.ts +1 -1
  32. package/types/frames/frame-client.d.ts +26 -0
  33. package/types/frames/frame-transport.d.ts +1 -1
  34. package/types/frames/serializer.d.ts +18 -160
  35. package/types/serializer-decode.d.ts +182 -0
  36. package/types/serializer.d.ts +18 -160
  37. package/types/server-functions/client.d.ts +1 -1
  38. package/types/server-functions/server.d.ts +1 -1
  39. package/types/server-functions/shared.d.ts +57 -1
  40. package/types/server.d.ts +21 -1
  41. package/types-cjs/client.d.cts +23 -1
  42. package/types-cjs/cookies.d.cts +93 -0
  43. package/types-cjs/core.d.cts +1 -1
  44. package/types-cjs/frames/frame-client.d.cts +26 -0
  45. package/types-cjs/frames/frame-transport.d.cts +1 -1
  46. package/types-cjs/frames/serializer.d.cts +18 -160
  47. package/types-cjs/serializer-decode.d.cts +182 -0
  48. package/types-cjs/serializer.d.cts +18 -160
  49. package/types-cjs/server-functions/client.d.cts +1 -1
  50. package/types-cjs/server-functions/server.d.cts +1 -1
  51. package/types-cjs/server-functions/shared.d.cts +57 -1
  52. package/types-cjs/server.d.cts +21 -1
@@ -1,53 +1,33 @@
1
- import { fromCrossJSON, Feature, toCrossJSONStream } from 'seroval';
2
- import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
3
-
4
1
  const REVALIDATE_HEADER = "X-Revalidate";
5
2
 
6
- Feature.AggregateError | Feature.BigIntTypedArray;
7
- const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : Feature.ErrorPrototypeStack;
8
- const DEFAULT_WEB_PLUGINS = Object.freeze([AbortSignalPlugin,
9
- CustomEventPlugin, DOMExceptionPlugin, EventPlugin,
10
- FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin]);
11
- function resolveSerializerPlugins(customPlugins) {
12
- return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
13
- }
14
- const JSON_CODEC_DISABLED_FEATURES = Feature.RegExp;
15
- const JSON_CODEC_DEPTH_LIMIT = 64;
16
- function resolveCodecOptions({
17
- plugins,
18
- disabledFeatures,
19
- depthLimit
20
- } = {}) {
21
- return {
22
- plugins: resolveSerializerPlugins(plugins),
23
- disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
24
- depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
25
- };
3
+ const SERVER_FUNCTION_METADATA = Symbol.for("solid.ServerFunctionMetadata");
4
+ function getServerFunctionMetadata(fn) {
5
+ if (typeof fn !== "function") return undefined;
6
+ return fn[SERVER_FUNCTION_METADATA] || undefined;
26
7
  }
27
- function serializeJSON(value, {
28
- onParse,
29
- onDone,
30
- onError,
31
- ...codecOptions
32
- }) {
33
- const resolved = resolveCodecOptions(codecOptions);
34
- return toCrossJSONStream(value, {
35
- onParse,
36
- onDone,
37
- onError,
38
- ...resolved,
39
- disabledFeatures: resolved.disabledFeatures | serializeOnlyDisabledFeatures()
40
- });
8
+ function isServerFunction(fn) {
9
+ return typeof fn === "function" && !!fn[SERVER_FUNCTION_METADATA];
41
10
  }
42
- function createJSONDeserializer(options) {
43
- const refs = new Map();
44
- const resolved = resolveCodecOptions(options);
45
- return function deserializeJSONChunk(node) {
46
- return fromCrossJSON(node, {
47
- refs,
48
- ...resolved
49
- });
50
- };
11
+ function withMeta(fn, meta) {
12
+ const metadata = getServerFunctionMetadata(fn);
13
+ if (!metadata) {
14
+ throw new Error("withMeta expects a server function reference");
15
+ }
16
+ Object.assign(metadata, meta);
17
+ return fn;
18
+ }
19
+ const SERVER_FUNCTION_RPC = Symbol.for("solid.ServerFunctionRPC");
20
+ function provideServerFunctionRPC(rpc) {
21
+ globalThis[SERVER_FUNCTION_RPC] || (globalThis[SERVER_FUNCTION_RPC] = rpc);
22
+ }
23
+
24
+ const FLASH_COOKIE = "flash";
25
+ const FLASH_MATCHER = new RegExp(`(?:^|;\\s*)${FLASH_COOKIE}=([^;]+)`);
26
+ function hasFlashCookie(cookieHeader) {
27
+ return !!cookieHeader && FLASH_MATCHER.test(cookieHeader);
28
+ }
29
+ function clearFlashCookie() {
30
+ return `${FLASH_COOKIE}=; Max-Age=0; Path=/`;
51
31
  }
52
32
 
53
33
  const codecConfig = {
@@ -115,22 +95,6 @@ function stableString(value, seen) {
115
95
  }
116
96
  return out + "}";
117
97
  }
118
- const SERVER_FUNCTION_METADATA = Symbol.for("solid.ServerFunctionMetadata");
119
- function getServerFunctionMetadata(fn) {
120
- if (typeof fn !== "function") return undefined;
121
- return fn[SERVER_FUNCTION_METADATA] || undefined;
122
- }
123
- function isServerFunction(fn) {
124
- return typeof fn === "function" && !!fn[SERVER_FUNCTION_METADATA];
125
- }
126
- function withMeta(fn, meta) {
127
- const metadata = getServerFunctionMetadata(fn);
128
- if (!metadata) {
129
- throw new Error("withMeta expects a server function reference");
130
- }
131
- Object.assign(metadata, meta);
132
- return fn;
133
- }
134
98
  const FUNCTION_HEADER = "X-Server-Function-Id";
135
99
  const ERROR_HEADER = "X-Server-Function-Error";
136
100
  const ERROR_HEADER_MARKER = "=?1?";
@@ -161,14 +125,6 @@ const INSTANCE_HEADER = "X-Server-Function-Instance";
161
125
  const BODY_FORMAT_HEADER = "X-Server-Function-Format";
162
126
  const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
163
127
  const FILE_FORM_KEY = "__server_function_file__";
164
- const FLASH_COOKIE = "flash";
165
- const FLASH_MATCHER = new RegExp(`(?:^|;\\s*)${FLASH_COOKIE}=([^;]+)`);
166
- function hasFlashCookie(cookieHeader) {
167
- return !!cookieHeader && FLASH_MATCHER.test(cookieHeader);
168
- }
169
- function clearFlashCookie() {
170
- return `${FLASH_COOKIE}=; Max-Age=0; Path=/`;
171
- }
172
128
  const BodyFormat = {
173
129
  Serialized: "0",
174
130
  String: "1",
@@ -180,6 +136,38 @@ const BodyFormat = {
180
136
  Uint8Array: "7",
181
137
  Json: "8"
182
138
  };
139
+ const JSON_SAFE_DEPTH_LIMIT = 10000;
140
+ const EXIT = {};
141
+ function isJSONSafe(value) {
142
+ const stack = [value];
143
+ const ancestors = new Set();
144
+ while (stack.length) {
145
+ const v = stack.pop();
146
+ if (v === EXIT) {
147
+ ancestors.delete(stack.pop());
148
+ continue;
149
+ }
150
+ if (v === null) continue;
151
+ const t = typeof v;
152
+ if (t === "string" || t === "boolean") continue;
153
+ if (t === "number") {
154
+ if (!Number.isFinite(v)) return false;
155
+ continue;
156
+ }
157
+ if (t !== "object") return false;
158
+ if (ancestors.has(v) || ancestors.size >= JSON_SAFE_DEPTH_LIMIT) return false;
159
+ ancestors.add(v);
160
+ stack.push(v, EXIT);
161
+ if (Array.isArray(v)) {
162
+ for (let i = 0; i < v.length; i++) stack.push(v[i]);
163
+ } else {
164
+ const proto = Object.getPrototypeOf(v);
165
+ if (proto !== Object.prototype && proto !== null) return false;
166
+ for (const k in v) stack.push(v[k]);
167
+ }
168
+ }
169
+ return true;
170
+ }
183
171
  function getHeadersAndBody(body) {
184
172
  switch (true) {
185
173
  case typeof body === "string":
@@ -339,7 +327,10 @@ class ChunkReader {
339
327
  }
340
328
  function serializeStream(value, codecOptions) {
341
329
  return new ReadableStream({
342
- start(controller) {
330
+ async start(controller) {
331
+ const {
332
+ serializeJSON
333
+ } = await import('@solidjs/web/serialization');
343
334
  serializeJSON(value, {
344
335
  ...codecOptions,
345
336
  onParse(node) {
@@ -366,6 +357,9 @@ async function deserializeStream(source, codecOptions) {
366
357
  const reader = new ChunkReader(source.body);
367
358
  const result = await reader.next();
368
359
  if (!result.done) {
360
+ const {
361
+ createJSONDeserializer
362
+ } = await import('@solidjs/web/serialization/decode');
369
363
  const deserializeChunk = createJSONDeserializer(codecOptions);
370
364
  function interpretChunk(chunk) {
371
365
  return deserializeChunk(JSON.parse(chunk));
@@ -398,21 +392,6 @@ const config = {
398
392
  responseHandler: undefined,
399
393
  serializeArgs: undefined
400
394
  };
401
- function isJSONSafe(value) {
402
- if (value === null) return true;
403
- const t = typeof value;
404
- if (t === "string" || t === "boolean") return true;
405
- if (t === "number") return Number.isFinite(value);
406
- if (t !== "object") return false;
407
- if (Array.isArray(value)) {
408
- for (const v of value) if (!isJSONSafe(v)) return false;
409
- return true;
410
- }
411
- const proto = Object.getPrototypeOf(value);
412
- if (proto !== Object.prototype && proto !== null) return false;
413
- for (const k in value) if (!isJSONSafe(value[k])) return false;
414
- return true;
415
- }
416
395
  function serializeArguments(args) {
417
396
  if (!config.serializeArgs) {
418
397
  throw new Error("Server function arguments are sent as JSON by default and these " + "arguments are not JSON-serializable. Call enableRichArguments() " + '(from "@solidjs/web/server-functions/rich-args") once at startup ' + "to send Dates, Maps, Sets, typed arrays, etc. through the codec — " + "or pass a single Blob/FormData/File argument, which has a native " + "HTTP encoding.");
@@ -433,6 +412,15 @@ function configureServerFunctionsClient({
433
412
  if (serializeArgs !== undefined) config.serializeArgs = serializeArgs;
434
413
  }
435
414
  let INSTANCE = 0;
415
+ let rpcProvided = false;
416
+ function provideRPC() {
417
+ if (rpcProvided) return;
418
+ rpcProvided = true;
419
+ provideServerFunctionRPC({
420
+ GET,
421
+ decodeResponse
422
+ });
423
+ }
436
424
  async function createRequest(base, id, instance, options, meta) {
437
425
  const headers = {
438
426
  ...options.headers,
@@ -472,31 +460,37 @@ async function initializeResponse(base, id, instance, options, args, meta) {
472
460
  }, meta);
473
461
  }
474
462
  }
475
- if (isJSONSafe(args)) {
476
- return createRequest(base, id, instance, {
477
- ...options,
478
- body: JSON.stringify(args),
479
- headers: {
480
- ...options.headers,
481
- "Content-Type": "application/json",
482
- [BODY_FORMAT_HEADER]: BodyFormat.Json
483
- }
484
- }, meta);
485
- }
486
- if (args.length > 1) {
487
- const trailing = getHeadersAndBody(args[args.length - 1]);
488
- const leading = args.slice(0, -1).map(arg => arg === undefined ? null : arg);
489
- if (trailing && isJSONSafe(leading)) {
490
- const target = base + (base.includes("?") ? "&" : "?") + "args=" + encodeURIComponent(JSON.stringify(leading));
491
- return createRequest(target, id, instance, {
463
+ try {
464
+ if (isJSONSafe(args)) {
465
+ return createRequest(base, id, instance, {
492
466
  ...options,
493
- body: trailing.body,
467
+ body: JSON.stringify(args),
494
468
  headers: {
495
469
  ...options.headers,
496
- ...trailing.headers
470
+ "Content-Type": "application/json",
471
+ [BODY_FORMAT_HEADER]: BodyFormat.Json
497
472
  }
498
473
  }, meta);
499
474
  }
475
+ } catch {
476
+ }
477
+ if (args.length > 1) {
478
+ try {
479
+ const trailing = getHeadersAndBody(args[args.length - 1]);
480
+ const leading = args.slice(0, -1).map(arg => arg === undefined ? null : arg);
481
+ if (trailing && isJSONSafe(leading)) {
482
+ const target = base + (base.includes("?") ? "&" : "?") + "args=" + encodeURIComponent(JSON.stringify(leading));
483
+ return createRequest(target, id, instance, {
484
+ ...options,
485
+ body: trailing.body,
486
+ headers: {
487
+ ...options.headers,
488
+ ...trailing.headers
489
+ }
490
+ }, meta);
491
+ }
492
+ } catch {
493
+ }
500
494
  }
501
495
  return createRequest(base, id, instance, {
502
496
  ...options,
@@ -548,6 +542,7 @@ async function fetchServerFunction(base, id, options, args, meta, callArgs = arg
548
542
  return result;
549
543
  }
550
544
  function createServerReference(id, name, base) {
545
+ provideRPC();
551
546
  const metadata = name === undefined ? {} : {
552
547
  name
553
548
  };
@@ -578,6 +573,7 @@ function GET(fn) {
578
573
  if (!isServerFunction(fn)) {
579
574
  throw new Error("GET expects a server function reference");
580
575
  }
576
+ provideRPC();
581
577
  const id = fn.id;
582
578
  const metadata = {
583
579
  ...getServerFunctionMetadata(fn)
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var seroval = require('seroval');
4
- var web = require('seroval-plugins/web');
5
3
  var solidJs = require('solid-js');
6
4
 
7
5
  const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
@@ -14,51 +12,70 @@ function isSafeError(value) {
14
12
  }
15
13
  const REVALIDATE_HEADER = "X-Revalidate";
16
14
 
17
- seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
18
- const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : seroval.Feature.ErrorPrototypeStack;
19
- const DEFAULT_WEB_PLUGINS = Object.freeze([web.AbortSignalPlugin,
20
- web.CustomEventPlugin, web.DOMExceptionPlugin, web.EventPlugin,
21
- web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin]);
22
- function resolveSerializerPlugins(customPlugins) {
23
- return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
15
+ const SERVER_FUNCTION_METADATA = Symbol.for("solid.ServerFunctionMetadata");
16
+ function getServerFunctionMetadata(fn) {
17
+ if (typeof fn !== "function") return undefined;
18
+ return fn[SERVER_FUNCTION_METADATA] || undefined;
24
19
  }
25
- const JSON_CODEC_DISABLED_FEATURES = seroval.Feature.RegExp;
26
- const JSON_CODEC_DEPTH_LIMIT = 64;
27
- function resolveCodecOptions({
28
- plugins,
29
- disabledFeatures,
30
- depthLimit
31
- } = {}) {
32
- return {
33
- plugins: resolveSerializerPlugins(plugins),
34
- disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
35
- depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
36
- };
20
+ function isServerFunction(fn) {
21
+ return typeof fn === "function" && !!fn[SERVER_FUNCTION_METADATA];
37
22
  }
38
- function serializeJSON(value, {
39
- onParse,
40
- onDone,
41
- onError,
42
- ...codecOptions
43
- }) {
44
- const resolved = resolveCodecOptions(codecOptions);
45
- return seroval.toCrossJSONStream(value, {
46
- onParse,
47
- onDone,
48
- onError,
49
- ...resolved,
50
- disabledFeatures: resolved.disabledFeatures | serializeOnlyDisabledFeatures()
51
- });
23
+ function withMeta(fn, meta) {
24
+ const metadata = getServerFunctionMetadata(fn);
25
+ if (!metadata) {
26
+ throw new Error("withMeta expects a server function reference");
27
+ }
28
+ Object.assign(metadata, meta);
29
+ return fn;
52
30
  }
53
- function createJSONDeserializer(options) {
54
- const refs = new Map();
55
- const resolved = resolveCodecOptions(options);
56
- return function deserializeJSONChunk(node) {
57
- return seroval.fromCrossJSON(node, {
58
- refs,
59
- ...resolved
60
- });
61
- };
31
+ const SERVER_FUNCTION_RPC = Symbol.for("solid.ServerFunctionRPC");
32
+ function provideServerFunctionRPC(rpc) {
33
+ globalThis[SERVER_FUNCTION_RPC] || (globalThis[SERVER_FUNCTION_RPC] = rpc);
34
+ }
35
+
36
+ function parseCookieHeader(header) {
37
+ const cookies = {};
38
+ if (!header) return cookies;
39
+ for (const part of header.split(";")) {
40
+ const eq = part.indexOf("=");
41
+ if (eq < 0) continue;
42
+ const name = decodeSafe(part.slice(0, eq).trim());
43
+ let value = part.slice(eq + 1).trim();
44
+ if (value.length > 1 && value[0] === '"' && value[value.length - 1] === '"') {
45
+ value = value.slice(1, -1);
46
+ }
47
+ cookies[name] = decodeSafe(value);
48
+ }
49
+ return cookies;
50
+ }
51
+ function decodeSafe(text) {
52
+ try {
53
+ return decodeURIComponent(text);
54
+ } catch {
55
+ return text;
56
+ }
57
+ }
58
+ function serializeCookie(name, value, options = {}) {
59
+ let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
60
+ cookie += `; Path=${options.path === undefined ? "/" : options.path}`;
61
+ if (options.domain) cookie += `; Domain=${options.domain}`;
62
+ if (options.maxAge !== undefined) cookie += `; Max-Age=${Math.trunc(options.maxAge)}`;
63
+ if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
64
+ if (options.httpOnly) cookie += "; HttpOnly";
65
+ if (options.secure) cookie += "; Secure";
66
+ if (options.sameSite) {
67
+ const sameSite = options.sameSite.toLowerCase();
68
+ cookie += `; SameSite=${sameSite === "none" ? "None" : sameSite === "strict" ? "Strict" : "Lax"}`;
69
+ }
70
+ return cookie;
71
+ }
72
+ const FLASH_COOKIE = "flash";
73
+ const FLASH_MATCHER = new RegExp(`(?:^|;\\s*)${FLASH_COOKIE}=([^;]+)`);
74
+ function hasFlashCookie(cookieHeader) {
75
+ return !!cookieHeader && FLASH_MATCHER.test(cookieHeader);
76
+ }
77
+ function clearFlashCookie() {
78
+ return `${FLASH_COOKIE}=; Max-Age=0; Path=/`;
62
79
  }
63
80
 
64
81
  const codecConfig = {
@@ -74,22 +91,6 @@ function subscribeFlightData(consumer) {
74
91
  return () => {
75
92
  };
76
93
  }
77
- const SERVER_FUNCTION_METADATA = Symbol.for("solid.ServerFunctionMetadata");
78
- function getServerFunctionMetadata(fn) {
79
- if (typeof fn !== "function") return undefined;
80
- return fn[SERVER_FUNCTION_METADATA] || undefined;
81
- }
82
- function isServerFunction(fn) {
83
- return typeof fn === "function" && !!fn[SERVER_FUNCTION_METADATA];
84
- }
85
- function withMeta(fn, meta) {
86
- const metadata = getServerFunctionMetadata(fn);
87
- if (!metadata) {
88
- throw new Error("withMeta expects a server function reference");
89
- }
90
- Object.assign(metadata, meta);
91
- return fn;
92
- }
93
94
  const FUNCTION_HEADER = "X-Server-Function-Id";
94
95
  const ERROR_HEADER = "X-Server-Function-Error";
95
96
  const ERROR_HEADER_MARKER = "=?1?";
@@ -120,14 +121,6 @@ const INSTANCE_HEADER = "X-Server-Function-Instance";
120
121
  const BODY_FORMAT_HEADER = "X-Server-Function-Format";
121
122
  const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
122
123
  const FILE_FORM_KEY = "__server_function_file__";
123
- const FLASH_COOKIE = "flash";
124
- const FLASH_MATCHER = new RegExp(`(?:^|;\\s*)${FLASH_COOKIE}=([^;]+)`);
125
- function hasFlashCookie(cookieHeader) {
126
- return !!cookieHeader && FLASH_MATCHER.test(cookieHeader);
127
- }
128
- function clearFlashCookie() {
129
- return `${FLASH_COOKIE}=; Max-Age=0; Path=/`;
130
- }
131
124
  const BodyFormat = {
132
125
  Serialized: "0",
133
126
  String: "1",
@@ -139,6 +132,38 @@ const BodyFormat = {
139
132
  Uint8Array: "7",
140
133
  Json: "8"
141
134
  };
135
+ const JSON_SAFE_DEPTH_LIMIT = 10000;
136
+ const EXIT = {};
137
+ function isJSONSafe(value) {
138
+ const stack = [value];
139
+ const ancestors = new Set();
140
+ while (stack.length) {
141
+ const v = stack.pop();
142
+ if (v === EXIT) {
143
+ ancestors.delete(stack.pop());
144
+ continue;
145
+ }
146
+ if (v === null) continue;
147
+ const t = typeof v;
148
+ if (t === "string" || t === "boolean") continue;
149
+ if (t === "number") {
150
+ if (!Number.isFinite(v)) return false;
151
+ continue;
152
+ }
153
+ if (t !== "object") return false;
154
+ if (ancestors.has(v) || ancestors.size >= JSON_SAFE_DEPTH_LIMIT) return false;
155
+ ancestors.add(v);
156
+ stack.push(v, EXIT);
157
+ if (Array.isArray(v)) {
158
+ for (let i = 0; i < v.length; i++) stack.push(v[i]);
159
+ } else {
160
+ const proto = Object.getPrototypeOf(v);
161
+ if (proto !== Object.prototype && proto !== null) return false;
162
+ for (const k in v) stack.push(v[k]);
163
+ }
164
+ }
165
+ return true;
166
+ }
142
167
  function getHeadersAndBody(body) {
143
168
  switch (true) {
144
169
  case typeof body === "string":
@@ -298,7 +323,10 @@ class ChunkReader {
298
323
  }
299
324
  function serializeStream(value, codecOptions) {
300
325
  return new ReadableStream({
301
- start(controller) {
326
+ async start(controller) {
327
+ const {
328
+ serializeJSON
329
+ } = await import('@solidjs/web/serialization');
302
330
  serializeJSON(value, {
303
331
  ...codecOptions,
304
332
  onParse(node) {
@@ -321,6 +349,9 @@ async function deserializeStream(source, codecOptions) {
321
349
  const reader = new ChunkReader(source.body);
322
350
  const result = await reader.next();
323
351
  if (!result.done) {
352
+ const {
353
+ createJSONDeserializer
354
+ } = await import('@solidjs/web/serialization/decode');
324
355
  const deserializeChunk = createJSONDeserializer(codecOptions);
325
356
  function interpretChunk(chunk) {
326
357
  return deserializeChunk(JSON.parse(chunk));
@@ -350,43 +381,6 @@ async function decodeResponsePayload(response, codecOptions) {
350
381
  };
351
382
  }
352
383
 
353
- function parseCookieHeader(header) {
354
- const cookies = {};
355
- if (!header) return cookies;
356
- for (const part of header.split(";")) {
357
- const eq = part.indexOf("=");
358
- if (eq < 0) continue;
359
- const name = decodeSafe(part.slice(0, eq).trim());
360
- let value = part.slice(eq + 1).trim();
361
- if (value.length > 1 && value[0] === '"' && value[value.length - 1] === '"') {
362
- value = value.slice(1, -1);
363
- }
364
- cookies[name] = decodeSafe(value);
365
- }
366
- return cookies;
367
- }
368
- function decodeSafe(text) {
369
- try {
370
- return decodeURIComponent(text);
371
- } catch {
372
- return text;
373
- }
374
- }
375
- function serializeCookie(name, value, options = {}) {
376
- let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
377
- cookie += `; Path=${options.path === undefined ? "/" : options.path}`;
378
- if (options.domain) cookie += `; Domain=${options.domain}`;
379
- if (options.maxAge !== undefined) cookie += `; Max-Age=${Math.trunc(options.maxAge)}`;
380
- if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
381
- if (options.httpOnly) cookie += "; HttpOnly";
382
- if (options.secure) cookie += "; Secure";
383
- if (options.sameSite) {
384
- const sameSite = options.sameSite.toLowerCase();
385
- cookie += `; SameSite=${sameSite === "none" ? "None" : sameSite === "strict" ? "Strict" : "Lax"}`;
386
- }
387
- return cookie;
388
- }
389
-
390
384
  const RequestContext = Symbol.for("solid.RequestContext");
391
385
  function getRequestEvent() {
392
386
  return globalThis[RequestContext] ? globalThis[RequestContext].getStore() || solidJs.sharedConfig.context && solidJs.sharedConfig.context.event || console.warn("RequestEvent is missing. This is most likely due to accessing `getRequestEvent` non-managed async scope in a partially polyfilled environment. Try moving it above all `await` calls.") : undefined;
@@ -550,7 +544,17 @@ function provideEvent(event, fn) {
550
544
  const REGISTRATIONS = new Map();
551
545
  const METHODS = new Map();
552
546
  const INVOCATIONS = new WeakMap();
547
+ let rpcProvided = false;
548
+ function provideRPC() {
549
+ if (rpcProvided) return;
550
+ rpcProvided = true;
551
+ provideServerFunctionRPC({
552
+ GET,
553
+ decodeResponse
554
+ });
555
+ }
553
556
  function registerServerFunction(id, callback) {
557
+ provideRPC();
554
558
  REGISTRATIONS.set(id, callback);
555
559
  return callback;
556
560
  }
@@ -575,6 +579,7 @@ function createServerReference({
575
579
  name
576
580
  }) {
577
581
  if (typeof fn !== "function") throw new Error("Export from a 'use server' module must be a function");
582
+ provideRPC();
578
583
  const metadata = name === undefined ? {} : {
579
584
  name
580
585
  };
@@ -686,7 +691,9 @@ async function foldFlightData(hook, event, headers, outcome, context = {}) {
686
691
  return transformed;
687
692
  }
688
693
  }
689
- return {
694
+ return outcome.value === undefined ? {
695
+ data
696
+ } : {
690
697
  value: outcome.value,
691
698
  data
692
699
  };
@@ -818,6 +825,23 @@ function encodeResult(value, headers, status, codec) {
818
825
  headers
819
826
  });
820
827
  }
828
+ if (value === undefined) {
829
+ return new Response(null, {
830
+ status,
831
+ headers
832
+ });
833
+ }
834
+ try {
835
+ if (isJSONSafe(value)) {
836
+ headers.set(BODY_FORMAT_HEADER, BodyFormat.Json);
837
+ headers.set("Content-Type", "application/json");
838
+ return new Response(JSON.stringify(value), {
839
+ status,
840
+ headers
841
+ });
842
+ }
843
+ } catch {
844
+ }
821
845
  const response = serializedResponse(value, headers, codec);
822
846
  return status === 200 ? response : new Response(response.body, {
823
847
  status,