@solidjs/web 2.0.0-beta.16 → 2.0.0-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/web.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createRenderEffect, createMemo, sharedConfig, untrack, runWithOwner, flatten, createRoot, merge, createComponent, omit, getOwner, createEffect, enableHydration, flush } from 'solid-js';
1
+ import { createRenderEffect, createMemo, sharedConfig, untrack, runWithOwner, flatten, createRoot, merge, createComponent, omit, createOwner, enableHydration, flush, getOwner, createEffect } from 'solid-js';
2
2
  export { Errored, For, Hydration, Loading, Match, NoHydration, Repeat, Reveal, Show, Switch, createComponent, getOwner, untrack } from 'solid-js';
3
3
 
4
4
  const DOMWithState = {
@@ -503,22 +503,117 @@ function assign(node, props, skipChildren, prevProps = {}, skipRef = false) {
503
503
  prevProps[prop] = assignProp(node, prop, props[prop], prevProps[prop], skipRef, nodeName);
504
504
  }
505
505
  }
506
+ const ASSET_REMOVAL_GRACE = 100;
507
+ const assetRegistry = new Map();
508
+ function assetEntryKey(descriptor) {
509
+ if (descriptor.policy === "exclusive") return "x|" + descriptor.key;
510
+ return descriptor.type === "inline-style" ? "i|" + descriptor.id : descriptor.type + "|" + descriptor.href;
511
+ }
512
+ function findAssetElement(selector, attr, value) {
513
+ const nodes = document.querySelectorAll(selector);
514
+ for (let i = 0; i < nodes.length; i++) {
515
+ if (nodes[i].getAttribute(attr) === value) return nodes[i];
516
+ }
517
+ return null;
518
+ }
519
+ function mountAssetElement(descriptor) {
520
+ let el;
521
+ if (descriptor.type === "inline-style") {
522
+ el = findAssetElement("style[data-asset]", "data-asset", descriptor.id);
523
+ if (!el) {
524
+ el = document.createElement("style");
525
+ el.setAttribute("data-asset", descriptor.id);
526
+ el.textContent = descriptor.content || "";
527
+ }
528
+ } else {
529
+ const rel = descriptor.type === "module" ? "modulepreload" : "stylesheet";
530
+ el = findAssetElement(`link[rel="${rel}"]`, "href", descriptor.href);
531
+ if (!el) {
532
+ el = document.createElement("link");
533
+ el.rel = rel;
534
+ el.href = descriptor.href;
535
+ }
536
+ }
537
+ if (descriptor.attrs) {
538
+ for (const name in descriptor.attrs) el.setAttribute(name, descriptor.attrs[name]);
539
+ }
540
+ if (!el.isConnected) document.head.appendChild(el);
541
+ return el;
542
+ }
543
+ function acquireAsset(descriptor) {
544
+ const key = assetEntryKey(descriptor);
545
+ let entry = assetRegistry.get(key);
546
+ if (descriptor.policy === "exclusive") {
547
+ if (!entry) {
548
+ entry = {
549
+ original: descriptor.get(),
550
+ set: descriptor.set,
551
+ writers: []
552
+ };
553
+ assetRegistry.set(key, entry);
554
+ }
555
+ const writer = {
556
+ value: descriptor.value
557
+ };
558
+ entry.writers.push(writer);
559
+ entry.set(writer.value);
560
+ let released = false;
561
+ return () => {
562
+ if (released) return;
563
+ released = true;
564
+ const index = entry.writers.indexOf(writer);
565
+ const wasTop = index === entry.writers.length - 1;
566
+ entry.writers.splice(index, 1);
567
+ if (!wasTop) return;
568
+ if (entry.writers.length) {
569
+ entry.set(entry.writers[entry.writers.length - 1].value);
570
+ } else {
571
+ entry.set(entry.original);
572
+ assetRegistry.delete(key);
573
+ }
574
+ };
575
+ }
576
+ if (!entry) {
577
+ entry = {
578
+ count: 0,
579
+ element: null,
580
+ timer: null
581
+ };
582
+ assetRegistry.set(key, entry);
583
+ }
584
+ if (entry.timer) {
585
+ clearTimeout(entry.timer);
586
+ entry.timer = null;
587
+ }
588
+ entry.count++;
589
+ if (!entry.element || !entry.element.isConnected) entry.element = mountAssetElement(descriptor);
590
+ let released = false;
591
+ return () => {
592
+ if (released) return;
593
+ released = true;
594
+ if (--entry.count > 0) return;
595
+ entry.timer = setTimeout(() => {
596
+ assetRegistry.delete(key);
597
+ entry.element && entry.element.remove();
598
+ }, ASSET_REMOVAL_GRACE);
599
+ };
600
+ }
506
601
  function loadModuleAssets(mapping) {
507
602
  const hy = globalThis._$HY;
508
603
  if (!hy) return;
509
604
  const pending = [];
510
- for (const moduleUrl in mapping) {
511
- if (hy.modules[moduleUrl]) continue;
512
- const entryUrl = mapping[moduleUrl];
513
- if (!hy.loading[moduleUrl]) {
514
- hy.loading[moduleUrl] = import(entryUrl).then(mod => {
515
- hy.modules[moduleUrl] = mod;
605
+ for (const key in mapping) {
606
+ if (hy.modules[key]) continue;
607
+ const entryUrl = mapping[key];
608
+ if (!hy.loading[key]) {
609
+ hy.loading[key] = import(entryUrl).then(mod => {
610
+ hy.modules[key] = mod;
516
611
  }, err => {
517
- delete hy.loading[moduleUrl];
612
+ delete hy.loading[key];
518
613
  throw err;
519
614
  });
520
615
  }
521
- pending.push(hy.loading[moduleUrl]);
616
+ pending.push(hy.loading[key]);
522
617
  }
523
618
  return pending.length ? Promise.all(pending).then(() => {}) : undefined;
524
619
  }
@@ -805,7 +900,12 @@ function insertExpression(parent, value, current, marker) {
805
900
  const tc = typeof current;
806
901
  if (tc === "string" || tc === "number") {
807
902
  parent.firstChild.data = value;
808
- } else parent.textContent = value;
903
+ } else {
904
+ if (ownsAllChildren(parent, current)) parent.textContent = value;else {
905
+ removeOwnedChildren(parent, current);
906
+ parent.insertBefore(document.createTextNode(value), parent.firstChild);
907
+ }
908
+ }
809
909
  } else if (value === undefined) {
810
910
  cleanChildren(parent, current, marker);
811
911
  } else if (value.nodeType) {
@@ -828,7 +928,7 @@ function insertExpression(parent, value, current, marker) {
828
928
  appendNodes(parent, value, marker);
829
929
  } else reconcileArrays(parent, current, value, marker);
830
930
  } else {
831
- current && cleanChildren(parent);
931
+ current && cleanChildren(parent, current);
832
932
  appendNodes(parent, value);
833
933
  }
834
934
  } else ;
@@ -868,8 +968,34 @@ function appendNodes(parent, array, marker = null) {
868
968
  if (marker) n[$$SLOT] = marker;
869
969
  }
870
970
  }
971
+ function ownsAllChildren(parent, current) {
972
+ if (current == null) return true;
973
+ if (Array.isArray(current)) {
974
+ return current.length ? parent.firstChild === current[0] && parent.lastChild === current[current.length - 1] : parent.firstChild === null;
975
+ }
976
+ if (current === "") return parent.firstChild === null;
977
+ if (current.nodeType) return parent.firstChild === current && parent.lastChild === current;
978
+ const first = parent.firstChild;
979
+ return first !== null && first.nodeType === 3 && parent.lastChild === first;
980
+ }
981
+ function removeOwnedChildren(parent, current) {
982
+ if (Array.isArray(current)) {
983
+ for (let i = 0; i < current.length; i++) {
984
+ const el = current[i];
985
+ if (el.parentNode === parent) el.remove();
986
+ }
987
+ } else if (current.nodeType) {
988
+ if (current.parentNode === parent) current.remove();
989
+ } else {
990
+ const first = parent.firstChild;
991
+ if (first && first.nodeType === 3) first.remove();
992
+ }
993
+ }
871
994
  function cleanChildren(parent, current, marker, replacement) {
872
- if (marker === undefined) return parent.textContent = "";
995
+ if (marker === undefined) {
996
+ if (ownsAllChildren(parent, current)) return parent.textContent = "";
997
+ return removeOwnedChildren(parent, current);
998
+ }
873
999
  if (current.length) {
874
1000
  let inserted = false;
875
1001
  for (let i = current.length - 1; i >= 0; i--) {
@@ -940,11 +1066,16 @@ const hydrate = (...args) => {
940
1066
  return hydrate$1(...args);
941
1067
  };
942
1068
  function Portal(props) {
1069
+ return runWithOwner(createOwner(), () => portalImpl(props));
1070
+ }
1071
+ function portalImpl(props) {
943
1072
  const treeMarker = document.createTextNode(""),
944
1073
  startMarker = document.createTextNode(""),
945
1074
  endMarker = document.createTextNode(""),
946
1075
  mount = () => props.mount || document.body,
947
- content = createMemo(() => [startMarker, props.children]);
1076
+ content = createMemo(() => [startMarker, props.children], {
1077
+ ssrSource: "client"
1078
+ });
948
1079
  createRenderEffect(
949
1080
  () => [mount(), content(), getOwner()], ([, c, owner]) => {
950
1081
  const m = untrack(mount);
@@ -965,8 +1096,10 @@ function Portal(props) {
965
1096
  c = n;
966
1097
  }
967
1098
  };
968
- }, {
969
- schedule: true
1099
+ },
1100
+ {
1101
+ schedule: true,
1102
+ ssrSource: "client"
970
1103
  });
971
1104
  createEffect(mount, () => {
972
1105
  const m = untrack(mount);
@@ -974,6 +1107,11 @@ function Portal(props) {
974
1107
  if (!ownerRoot || ownerRoot.contains(m)) return;
975
1108
  registerDelegatedContainer(m, ownerRoot);
976
1109
  return () => unregisterDelegatedContainer(m, ownerRoot);
1110
+ }, {
1111
+ ssrSource: "client"
1112
+ });
1113
+ if (sharedConfig.hydrating) return createMemo(() => treeMarker, {
1114
+ ssrSource: "client"
977
1115
  });
978
1116
  return treeMarker;
979
1117
  }
@@ -1005,4 +1143,4 @@ function createElement(tagName, is = undefined) {
1005
1143
  });
1006
1144
  }
1007
1145
 
1008
- export { voidFn as Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, SVGElements, VoidElements, addEvent, applyRef, assign, className, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, voidFn as getAssets, getDelegatedRoot, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, hydrate, insert, isDev, isServer, memo, mergeProps, ref, registerDelegatedContainer, registerDelegatedRoot, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, scope, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, voidFn as useAssets };
1146
+ export { voidFn as Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, className, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, voidFn as getAssets, getDelegatedRoot, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, hydrate, insert, isDev, isServer, memo, mergeProps, ref, registerDelegatedContainer, registerDelegatedRoot, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, scope, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, voidFn as useAssets };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@solidjs/web",
3
3
  "description": "Solid's web runtime: client rendering, hydration, SSR, and DOM-specific control flow (Portal, Dynamic).",
4
- "version": "2.0.0-beta.16",
4
+ "version": "2.0.0-beta.18",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
7
7
  "homepage": "https://solidjs.com",
@@ -27,7 +27,11 @@
27
27
  "storage/dist",
28
28
  "storage/types",
29
29
  "storage/types-cjs",
30
- "storage/package.json"
30
+ "storage/package.json",
31
+ "serialization/dist",
32
+ "serialization/types",
33
+ "serialization/types-cjs",
34
+ "serialization/package.json"
31
35
  ],
32
36
  "exports": {
33
37
  ".": {
@@ -130,30 +134,41 @@
130
134
  "default": "./storage/dist/storage.cjs"
131
135
  }
132
136
  },
137
+ "./serialization": {
138
+ "import": {
139
+ "types": "./serialization/types/index.d.ts",
140
+ "default": "./serialization/dist/serialization.js"
141
+ },
142
+ "require": {
143
+ "types": "./serialization/types-cjs/index.d.cts",
144
+ "default": "./serialization/dist/serialization.cjs"
145
+ }
146
+ },
133
147
  "./types/*": "./types/*"
134
148
  },
135
149
  "dependencies": {
136
- "seroval": "^1.1.0",
137
- "seroval-plugins": "^1.1.0"
150
+ "seroval": "~1.5.4",
151
+ "seroval-plugins": "~1.5.4"
138
152
  },
139
153
  "peerDependencies": {
140
- "solid-js": "^2.0.0-beta.16"
154
+ "solid-js": "^2.0.0-beta.18"
141
155
  },
142
156
  "devDependencies": {
143
- "solid-js": "2.0.0-beta.16"
157
+ "solid-js": "2.0.0-beta.18"
144
158
  },
145
159
  "scripts": {
146
160
  "build": "npm-run-all -nl build:clean types:copy-jsx build:js",
147
161
  "build:clean": "rimraf dist/",
148
162
  "build:js": "rollup -c",
149
163
  "link": "symlink-dir . node_modules/@solidjs/web",
150
- "types": "npm-run-all -nl types:clean types:copy-jsx types:web types:copy-web types:web-storage types:cjs",
151
- "types:clean": "rimraf types/ types-cjs/ storage/types-cjs/",
164
+ "types": "npm-run-all -nl types:clean types:copy-jsx types:web types:copy-web types:web-storage types:copy-serialization types:cjs",
165
+ "types:clean": "rimraf types/ types-cjs/ storage/types/ storage/types-cjs/ serialization/types/ serialization/types-cjs/",
152
166
  "types:copy-jsx": "ncp ../../node_modules/@dom-expressions/runtime/src/jsx.d.ts ./src/jsx.d.ts && ncp ../../node_modules/@dom-expressions/runtime/src/jsx-properties.d.ts ./src/jsx-properties.d.ts && dom-expressions-jsx-types --input ./src/jsx.d.ts --element \"SolidElement | Node | ArrayElement\" --import 'import type { Element as SolidElement } from \"solid-js\";'",
153
167
  "types:web": "tsc --project ./tsconfig.build.json",
154
- "types:copy-web": "ncp ../../node_modules/@dom-expressions/runtime/src/client.d.ts ./types/client.d.ts && ncp ../../node_modules/@dom-expressions/runtime/src/server.d.ts ./types/server.d.ts && ncp ./src/jsx.d.ts ./types/jsx.d.ts && ncp ./src/jsx-properties.d.ts ./types/jsx-properties.d.ts",
168
+ "types:copy-web": "ncp ../../node_modules/@dom-expressions/runtime/src/client.d.ts ./types/client.d.ts && ncp ../../node_modules/@dom-expressions/runtime/src/server.d.ts ./types/server.d.ts && ncp ../../node_modules/@dom-expressions/runtime/src/serializer.d.ts ./types/serializer.d.ts && ncp ./src/jsx.d.ts ./types/jsx.d.ts && ncp ./src/jsx-properties.d.ts ./types/jsx-properties.d.ts",
155
169
  "types:web-storage": "tsc --project ./storage/tsconfig.build.json",
156
- "types:cjs": "node ../../scripts/sync-dual-types.mjs ./types ./types-cjs ./storage/types ./storage/types-cjs",
170
+ "types:copy-serialization": "node -e \"fs.mkdirSync('./serialization/types', { recursive: true }); fs.copyFileSync('../../node_modules/@dom-expressions/runtime/src/serializer.d.ts', './serialization/types/index.d.ts');\"",
171
+ "types:cjs": "node ../../scripts/sync-dual-types.mjs ./types ./types-cjs ./storage/types ./storage/types-cjs ./serialization/types ./serialization/types-cjs",
157
172
  "test": "vitest run && vitest run --config vite.config.server.mjs && vitest run --config vite.config.hydrate.mjs",
158
173
  "test:server": "vitest run --config vite.config.server.mjs",
159
174
  "coverage": "vitest run --coverage",
@@ -0,0 +1,83 @@
1
+ 'use strict';
2
+
3
+ var seroval = require('seroval');
4
+ var web = require('seroval-plugins/web');
5
+
6
+ const DEFAULT_DISABLED_FEATURES = seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
7
+ const HYDRATION_GLOBAL = "_$HY.r";
8
+ const DEFAULT_WEB_PLUGINS = Object.freeze([web.AbortSignalPlugin,
9
+ web.CustomEventPlugin, web.DOMExceptionPlugin, web.EventPlugin,
10
+ web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin]);
11
+ function resolveSerializerPlugins(customPlugins) {
12
+ return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
13
+ }
14
+ function createSerializer(options) {
15
+ return new seroval.Serializer({
16
+ ...options,
17
+ plugins: resolveSerializerPlugins(options.plugins),
18
+ disabledFeatures: options.disabledFeatures === undefined ? DEFAULT_DISABLED_FEATURES : options.disabledFeatures
19
+ });
20
+ }
21
+ function createHydrationSerializer({
22
+ onData,
23
+ onDone,
24
+ scopeId,
25
+ onError,
26
+ plugins
27
+ }) {
28
+ return createSerializer({
29
+ scopeId,
30
+ plugins,
31
+ globalIdentifier: HYDRATION_GLOBAL,
32
+ onData,
33
+ onDone,
34
+ onError
35
+ });
36
+ }
37
+ function getLocalHeaderScript(id) {
38
+ return seroval.getCrossReferenceHeader(id) + ";";
39
+ }
40
+ const JSON_CODEC_DISABLED_FEATURES = seroval.Feature.RegExp;
41
+ const JSON_CODEC_DEPTH_LIMIT = 64;
42
+ function resolveCodecOptions({
43
+ plugins,
44
+ disabledFeatures,
45
+ depthLimit
46
+ } = {}) {
47
+ return {
48
+ plugins: resolveSerializerPlugins(plugins),
49
+ disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
50
+ depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
51
+ };
52
+ }
53
+ function serializeJSON(value, {
54
+ onParse,
55
+ onDone,
56
+ onError,
57
+ ...codecOptions
58
+ }) {
59
+ return seroval.toCrossJSONStream(value, {
60
+ onParse,
61
+ onDone,
62
+ onError,
63
+ ...resolveCodecOptions(codecOptions)
64
+ });
65
+ }
66
+ function createJSONDeserializer(options) {
67
+ const refs = new Map();
68
+ const resolved = resolveCodecOptions(options);
69
+ return function deserializeJSONChunk(node) {
70
+ return seroval.fromCrossJSON(node, {
71
+ refs,
72
+ ...resolved
73
+ });
74
+ };
75
+ }
76
+
77
+ exports.DEFAULT_WEB_PLUGINS = DEFAULT_WEB_PLUGINS;
78
+ exports.createHydrationSerializer = createHydrationSerializer;
79
+ exports.createJSONDeserializer = createJSONDeserializer;
80
+ exports.createSerializer = createSerializer;
81
+ exports.getLocalHeaderScript = getLocalHeaderScript;
82
+ exports.resolveSerializerPlugins = resolveSerializerPlugins;
83
+ exports.serializeJSON = serializeJSON;
@@ -0,0 +1,75 @@
1
+ import { Feature, Serializer, getCrossReferenceHeader, toCrossJSONStream, fromCrossJSON } from 'seroval';
2
+ import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
3
+
4
+ const DEFAULT_DISABLED_FEATURES = Feature.AggregateError | Feature.BigIntTypedArray;
5
+ const HYDRATION_GLOBAL = "_$HY.r";
6
+ const DEFAULT_WEB_PLUGINS = Object.freeze([AbortSignalPlugin,
7
+ CustomEventPlugin, DOMExceptionPlugin, EventPlugin,
8
+ FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin]);
9
+ function resolveSerializerPlugins(customPlugins) {
10
+ return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
11
+ }
12
+ function createSerializer(options) {
13
+ return new Serializer({
14
+ ...options,
15
+ plugins: resolveSerializerPlugins(options.plugins),
16
+ disabledFeatures: options.disabledFeatures === undefined ? DEFAULT_DISABLED_FEATURES : options.disabledFeatures
17
+ });
18
+ }
19
+ function createHydrationSerializer({
20
+ onData,
21
+ onDone,
22
+ scopeId,
23
+ onError,
24
+ plugins
25
+ }) {
26
+ return createSerializer({
27
+ scopeId,
28
+ plugins,
29
+ globalIdentifier: HYDRATION_GLOBAL,
30
+ onData,
31
+ onDone,
32
+ onError
33
+ });
34
+ }
35
+ function getLocalHeaderScript(id) {
36
+ return getCrossReferenceHeader(id) + ";";
37
+ }
38
+ const JSON_CODEC_DISABLED_FEATURES = Feature.RegExp;
39
+ const JSON_CODEC_DEPTH_LIMIT = 64;
40
+ function resolveCodecOptions({
41
+ plugins,
42
+ disabledFeatures,
43
+ depthLimit
44
+ } = {}) {
45
+ return {
46
+ plugins: resolveSerializerPlugins(plugins),
47
+ disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
48
+ depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
49
+ };
50
+ }
51
+ function serializeJSON(value, {
52
+ onParse,
53
+ onDone,
54
+ onError,
55
+ ...codecOptions
56
+ }) {
57
+ return toCrossJSONStream(value, {
58
+ onParse,
59
+ onDone,
60
+ onError,
61
+ ...resolveCodecOptions(codecOptions)
62
+ });
63
+ }
64
+ function createJSONDeserializer(options) {
65
+ const refs = new Map();
66
+ const resolved = resolveCodecOptions(options);
67
+ return function deserializeJSONChunk(node) {
68
+ return fromCrossJSON(node, {
69
+ refs,
70
+ ...resolved
71
+ });
72
+ };
73
+ }
74
+
75
+ export { DEFAULT_WEB_PLUGINS, createHydrationSerializer, createJSONDeserializer, createSerializer, getLocalHeaderScript, resolveSerializerPlugins, serializeJSON };
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@solidjs/web/serialization",
3
+ "main": "./dist/serialization.cjs",
4
+ "module": "./dist/serialization.js",
5
+ "types": "./types/index.d.ts",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./types/index.d.ts",
12
+ "default": "./dist/serialization.js"
13
+ },
14
+ "require": {
15
+ "types": "./types-cjs/index.d.cts",
16
+ "default": "./dist/serialization.cjs"
17
+ }
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,97 @@
1
+ import { Plugin, Serializer, SerovalNode } from "seroval";
2
+
3
+ export type { SerovalNode };
4
+
5
+ /** A Seroval plugin usable with the web serializers. */
6
+ export type SerializerPlugin = Plugin<any, any>;
7
+
8
+ /**
9
+ * Baseline plugin set for serializing web-platform values (AbortSignal,
10
+ * Event, FormData, Headers, ReadableStream, Request, Response, URL, ...).
11
+ */
12
+ export const DEFAULT_WEB_PLUGINS: readonly SerializerPlugin[];
13
+
14
+ /**
15
+ * Composes custom plugins with `DEFAULT_WEB_PLUGINS`. Custom plugins come
16
+ * first so they can shadow a default for values both would match. Returns a
17
+ * fresh array; the defaults are never mutated.
18
+ */
19
+ export function resolveSerializerPlugins(customPlugins?: SerializerPlugin[]): SerializerPlugin[];
20
+
21
+ export interface WebSerializerOptions {
22
+ /** Name of the global object the emitted scripts write resolved values into. */
23
+ globalIdentifier: string;
24
+ scopeId?: string;
25
+ /**
26
+ * Seroval feature bitflags to exclude from output. Defaults to disabling
27
+ * post-ES2017 features (AggregateError, BigInt typed arrays).
28
+ */
29
+ disabledFeatures?: number;
30
+ /** Extra plugins, composed ahead of `DEFAULT_WEB_PLUGINS`. */
31
+ plugins?: SerializerPlugin[];
32
+ onData: (result: string) => void;
33
+ onError?: (error: unknown) => void;
34
+ onDone?: () => void;
35
+ }
36
+
37
+ /**
38
+ * Creates a streaming Seroval serializer preconfigured with the web plugin
39
+ * set and the default feature policy.
40
+ */
41
+ export function createSerializer(options: WebSerializerOptions): Serializer;
42
+
43
+ export type HydrationSerializerOptions = Omit<
44
+ WebSerializerOptions,
45
+ "globalIdentifier" | "disabledFeatures"
46
+ >;
47
+
48
+ /**
49
+ * Serializer for SSR hydration output. Pins the hydration global (`_$HY.r`)
50
+ * and feature policy — only the wiring options (callbacks, scope, extra
51
+ * plugins) are configurable.
52
+ */
53
+ export function createHydrationSerializer(options: HydrationSerializerOptions): Serializer;
54
+
55
+ /** Returns the cross-reference bootstrap script for a render scope. */
56
+ export function getLocalHeaderScript(id?: string): string;
57
+
58
+ // ---- JSON codec (server function transports) ----
59
+
60
+ export interface JSONCodecOptions {
61
+ /** Extra plugins, composed ahead of `DEFAULT_WEB_PLUGINS`. Must match on both peers. */
62
+ plugins?: SerializerPlugin[];
63
+ /**
64
+ * Seroval feature bitflags to exclude. Defaults to disabling `RegExp`
65
+ * (payloads may come from an untrusted peer). Must match on both peers.
66
+ */
67
+ disabledFeatures?: number;
68
+ /** Maximum parse/deserialize depth. Defaults to 64. Must match on both peers. */
69
+ depthLimit?: number;
70
+ }
71
+
72
+ export interface JSONSerializeOptions extends JSONCodecOptions {
73
+ /**
74
+ * Receives each serialized node; `initial` is true for the first chunk
75
+ * (the source value itself). Async values produce additional chunks as
76
+ * they resolve.
77
+ */
78
+ onParse: (node: SerovalNode, initial: boolean) => void;
79
+ onError?: (error: unknown) => void;
80
+ /** Fires once all async values have settled. */
81
+ onDone?: () => void;
82
+ }
83
+
84
+ /**
85
+ * Serializes `value` as SerovalNode chunks delivered through `onParse`.
86
+ * Wire framing of the nodes is the transport's concern. Returns a cancel
87
+ * function that aborts pending async serialization.
88
+ */
89
+ export function serializeJSON(value: unknown, options: JSONSerializeOptions): () => void;
90
+
91
+ /**
92
+ * Creates the decoding counterpart of `serializeJSON`. Cross-references
93
+ * between chunks resolve through state shared across calls, so all chunks
94
+ * from one stream must go through the same deserializer instance. The first
95
+ * chunk's return value is the decoded source value.
96
+ */
97
+ export function createJSONDeserializer(options?: JSONCodecOptions): <T>(node: SerovalNode) => T;
@@ -0,0 +1,97 @@
1
+ import { Plugin, Serializer, SerovalNode } from "seroval";
2
+
3
+ export type { SerovalNode };
4
+
5
+ /** A Seroval plugin usable with the web serializers. */
6
+ export type SerializerPlugin = Plugin<any, any>;
7
+
8
+ /**
9
+ * Baseline plugin set for serializing web-platform values (AbortSignal,
10
+ * Event, FormData, Headers, ReadableStream, Request, Response, URL, ...).
11
+ */
12
+ export const DEFAULT_WEB_PLUGINS: readonly SerializerPlugin[];
13
+
14
+ /**
15
+ * Composes custom plugins with `DEFAULT_WEB_PLUGINS`. Custom plugins come
16
+ * first so they can shadow a default for values both would match. Returns a
17
+ * fresh array; the defaults are never mutated.
18
+ */
19
+ export function resolveSerializerPlugins(customPlugins?: SerializerPlugin[]): SerializerPlugin[];
20
+
21
+ export interface WebSerializerOptions {
22
+ /** Name of the global object the emitted scripts write resolved values into. */
23
+ globalIdentifier: string;
24
+ scopeId?: string;
25
+ /**
26
+ * Seroval feature bitflags to exclude from output. Defaults to disabling
27
+ * post-ES2017 features (AggregateError, BigInt typed arrays).
28
+ */
29
+ disabledFeatures?: number;
30
+ /** Extra plugins, composed ahead of `DEFAULT_WEB_PLUGINS`. */
31
+ plugins?: SerializerPlugin[];
32
+ onData: (result: string) => void;
33
+ onError?: (error: unknown) => void;
34
+ onDone?: () => void;
35
+ }
36
+
37
+ /**
38
+ * Creates a streaming Seroval serializer preconfigured with the web plugin
39
+ * set and the default feature policy.
40
+ */
41
+ export function createSerializer(options: WebSerializerOptions): Serializer;
42
+
43
+ export type HydrationSerializerOptions = Omit<
44
+ WebSerializerOptions,
45
+ "globalIdentifier" | "disabledFeatures"
46
+ >;
47
+
48
+ /**
49
+ * Serializer for SSR hydration output. Pins the hydration global (`_$HY.r`)
50
+ * and feature policy — only the wiring options (callbacks, scope, extra
51
+ * plugins) are configurable.
52
+ */
53
+ export function createHydrationSerializer(options: HydrationSerializerOptions): Serializer;
54
+
55
+ /** Returns the cross-reference bootstrap script for a render scope. */
56
+ export function getLocalHeaderScript(id?: string): string;
57
+
58
+ // ---- JSON codec (server function transports) ----
59
+
60
+ export interface JSONCodecOptions {
61
+ /** Extra plugins, composed ahead of `DEFAULT_WEB_PLUGINS`. Must match on both peers. */
62
+ plugins?: SerializerPlugin[];
63
+ /**
64
+ * Seroval feature bitflags to exclude. Defaults to disabling `RegExp`
65
+ * (payloads may come from an untrusted peer). Must match on both peers.
66
+ */
67
+ disabledFeatures?: number;
68
+ /** Maximum parse/deserialize depth. Defaults to 64. Must match on both peers. */
69
+ depthLimit?: number;
70
+ }
71
+
72
+ export interface JSONSerializeOptions extends JSONCodecOptions {
73
+ /**
74
+ * Receives each serialized node; `initial` is true for the first chunk
75
+ * (the source value itself). Async values produce additional chunks as
76
+ * they resolve.
77
+ */
78
+ onParse: (node: SerovalNode, initial: boolean) => void;
79
+ onError?: (error: unknown) => void;
80
+ /** Fires once all async values have settled. */
81
+ onDone?: () => void;
82
+ }
83
+
84
+ /**
85
+ * Serializes `value` as SerovalNode chunks delivered through `onParse`.
86
+ * Wire framing of the nodes is the transport's concern. Returns a cancel
87
+ * function that aborts pending async serialization.
88
+ */
89
+ export function serializeJSON(value: unknown, options: JSONSerializeOptions): () => void;
90
+
91
+ /**
92
+ * Creates the decoding counterpart of `serializeJSON`. Cross-references
93
+ * between chunks resolve through state shared across calls, so all chunks
94
+ * from one stream must go through the same deserializer instance. The first
95
+ * chunk's return value is the decoded source value.
96
+ */
97
+ export function createJSONDeserializer(options?: JSONCodecOptions): <T>(node: SerovalNode) => T;