@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/server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createRenderEffect, createMemo, sharedConfig, createRoot, ssrHandleError, getOwner, runWithOwner, createComponent, omit, getNextChildId, NotReadyError } from 'solid-js';
2
2
  export { Errored, For, Hydration, Loading, Match, NoHydration, Repeat, Reveal, Show, Switch, createComponent, getOwner, merge as mergeProps, ssrScope as scope, untrack } from 'solid-js';
3
- import { Serializer, Feature, getCrossReferenceHeader } from 'seroval';
3
+ import { Serializer, getCrossReferenceHeader, Feature } from 'seroval';
4
4
  import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
5
5
 
6
6
  const DOMWithState = {
@@ -65,25 +65,32 @@ const effect = (fn, effectFn, options) => createRenderEffect(fn, effectFn, optio
65
65
  } : transparentOptions);
66
66
  const memo = fn => createMemo(() => fn(), syncOptions);
67
67
 
68
- const ES2017FLAG = Feature.AggregateError |
69
- Feature.BigIntTypedArray;
70
- const GLOBAL_IDENTIFIER = "_$HY.r";
71
- function createSerializer({
68
+ const DEFAULT_DISABLED_FEATURES = Feature.AggregateError | Feature.BigIntTypedArray;
69
+ const HYDRATION_GLOBAL = "_$HY.r";
70
+ const DEFAULT_WEB_PLUGINS = Object.freeze([AbortSignalPlugin,
71
+ CustomEventPlugin, DOMExceptionPlugin, EventPlugin,
72
+ FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin]);
73
+ function resolveSerializerPlugins(customPlugins) {
74
+ return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
75
+ }
76
+ function createSerializer(options) {
77
+ return new Serializer({
78
+ ...options,
79
+ plugins: resolveSerializerPlugins(options.plugins),
80
+ disabledFeatures: options.disabledFeatures === undefined ? DEFAULT_DISABLED_FEATURES : options.disabledFeatures
81
+ });
82
+ }
83
+ function createHydrationSerializer({
72
84
  onData,
73
85
  onDone,
74
86
  scopeId,
75
87
  onError,
76
- plugins: customPlugins
88
+ plugins
77
89
  }) {
78
- const defaultPlugins = [AbortSignalPlugin,
79
- CustomEventPlugin, DOMExceptionPlugin, EventPlugin,
80
- FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin];
81
- const allPlugins = customPlugins ? [...customPlugins, ...defaultPlugins] : defaultPlugins;
82
- return new Serializer({
90
+ return createSerializer({
83
91
  scopeId,
84
- plugins: allPlugins,
85
- globalIdentifier: GLOBAL_IDENTIFIER,
86
- disabledFeatures: ES2017FLAG,
92
+ plugins,
93
+ globalIdentifier: HYDRATION_GLOBAL,
87
94
  onData,
88
95
  onDone,
89
96
  onError
@@ -92,6 +99,7 @@ function createSerializer({
92
99
  function getLocalHeaderScript(id) {
93
100
  return getCrossReferenceHeader(id) + ";";
94
101
  }
102
+ Feature.RegExp;
95
103
 
96
104
  function joinAssetPath(base, file) {
97
105
  if (/^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(file)) return file;
@@ -123,7 +131,7 @@ function resolveAssets(moduleUrl, manifest) {
123
131
  };
124
132
  }
125
133
  function registerEntryAssets(manifest) {
126
- if (!manifest) return;
134
+ if (!manifest || typeof manifest === "function" || typeof manifest.resolve === "function") return;
127
135
  const ctx = sharedConfig.context;
128
136
  if (!ctx?.registerAsset) return;
129
137
  for (const key in manifest) {
@@ -140,25 +148,48 @@ function createAssetTracking() {
140
148
  const boundaryModules = new Map();
141
149
  const boundaryStyles = new Map();
142
150
  const emittedAssets = new Set();
151
+ const inlineStyles = new Map();
143
152
  let currentBoundaryId = null;
144
153
  return {
145
154
  boundaryModules,
146
155
  boundaryStyles,
147
156
  emittedAssets,
157
+ inlineStyles,
158
+ registerInlineStyle(desc) {
159
+ let entry = inlineStyles.get(desc.id);
160
+ if (!entry) {
161
+ entry = {
162
+ id: desc.id,
163
+ content: desc.content || "",
164
+ attrs: desc.attrs,
165
+ emitted: false
166
+ };
167
+ inlineStyles.set(desc.id, entry);
168
+ }
169
+ if (currentBoundaryId) {
170
+ let styles = boundaryStyles.get(currentBoundaryId);
171
+ if (!styles) {
172
+ styles = new Set();
173
+ boundaryStyles.set(currentBoundaryId, styles);
174
+ }
175
+ styles.add(entry);
176
+ }
177
+ return entry;
178
+ },
148
179
  get currentBoundaryId() {
149
180
  return currentBoundaryId;
150
181
  },
151
182
  set currentBoundaryId(v) {
152
183
  currentBoundaryId = v;
153
184
  },
154
- registerModule(moduleUrl, entryUrl) {
185
+ registerModule(key, entryUrl) {
155
186
  const id = currentBoundaryId || "";
156
187
  let map = boundaryModules.get(id);
157
188
  if (!map) {
158
189
  map = {};
159
190
  boundaryModules.set(id, map);
160
191
  }
161
- map[moduleUrl] = entryUrl;
192
+ map[key] = entryUrl;
162
193
  },
163
194
  getBoundaryModules(id) {
164
195
  return boundaryModules.get(id) || null;
@@ -181,10 +212,21 @@ function applyAssetTracking(context, tracking, manifest) {
181
212
  });
182
213
  context.registerModule = tracking.registerModule;
183
214
  context.getBoundaryModules = tracking.getBoundaryModules;
184
- if (manifest) context.resolveAssets = moduleUrl => resolveAssets(moduleUrl, manifest);
215
+ if (typeof manifest === "function") {
216
+ context.resolveAssets = manifest;
217
+ } else if (manifest && typeof manifest.resolve === "function") {
218
+ context.resolveAssets = key => manifest.resolve(key);
219
+ if (typeof manifest.resolveSync === "function") {
220
+ context.resolveAssetsSync = key => manifest.resolveSync(key);
221
+ }
222
+ } else if (manifest) {
223
+ const resolve = moduleUrl => resolveAssets(moduleUrl, manifest);
224
+ context.resolveAssets = resolve;
225
+ context.resolveAssetsSync = resolve;
226
+ }
185
227
  }
186
228
  const VOID_ELEMENTS = /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i;
187
- const REPLACE_SCRIPT = `function $df(e,n,o,t){if(!(n=document.getElementById(e))||!(o=document.getElementById("pl-"+e)))return 0;for(;o&&8!==o.nodeType&&o.nodeValue!=="pl-"+e;)t=o.nextSibling,o.remove(),o=t;_$HY.done?o.remove():o.replaceWith(n.content),n.remove(),_$HY.fe(e);return 1}function $dfl(e,o,n){if(!(o=document.getElementById("pl-"+e)))return 0;if(o._$fl)return 1;for(n=o.nextSibling;n;){if(8===n.nodeType&&n.nodeValue==="pl-"+e){o.parentNode&&o.parentNode.insertBefore(o.content.cloneNode(!0),n),o._$fl=1;return 1}n=n.nextSibling}return 0}function $dflj(e,i){for(i=0;i<e.length;i++)$dfl(e[i])}function $dfs(e,c,d){(_$HY.sc=_$HY.sc||{})[e]=c,d&&((_$HY.sd=_$HY.sd||{})[e]=1)}function $dfg(e,g,i,k){if(!(g=_$HY.sg&&_$HY.sg[e]))return;for(i=0;i<g.length;i++)if(_$HY.sc&&_$HY.sc[g[i]]>0)return;for(i=0;i<g.length;i++)k=g[i],delete _$HY.sg[k],$df(k)}function $dfc(e){if(--_$HY.sc[e]<=0){delete _$HY.sc[e],_$HY.sg&&_$HY.sg[e]?$dfg(e):!(_$HY.sd&&_$HY.sd[e])&&$df(e);_$HY.sd&&delete _$HY.sd[e]}}function $dfj(e,i,n){for(i=0;i<e.length;i++)if(_$HY.sc&&_$HY.sc[e[i]]>0){for(n=0;n<e.length;n++)(_$HY.sg=_$HY.sg||{})[e[n]]=e;return}for(i=0;i<e.length;i++)$df(e[i])}`;
229
+ const REPLACE_SCRIPT = `function $df(e,n,o,t){if(!(n=document.getElementById(e)))return 0;if(!(o=document.getElementById("pl-"+e)))return(_$HY.dq=_$HY.dq||{})[e]=1,0;for(;o&&(8!==o.nodeType||o.nodeValue!=="pl-"+e);)t=o.nextSibling,o.remove(),o=t;_$HY.done?o.remove():o.replaceWith(n.content),n.remove(),_$HY.fe(e),$dfd();return 1}function $dfl(e,o,n){if(!(o=document.getElementById("pl-"+e)))return(_$HY.dlq=_$HY.dlq||{})[e]=1,0;if(o._$fl)return 1;for(n=o.nextSibling;n;){if(8===n.nodeType&&n.nodeValue==="pl-"+e){o.parentNode&&o.parentNode.insertBefore(o.content.cloneNode(!0),n),o._$fl=1,$dfd();return 1}n=n.nextSibling}return 0}function $dflj(e,i){for(i=0;i<e.length;i++)$dfl(e[i])}function $dfd(e,i){if(e=_$HY.dq){_$HY.dq=0;for(i in e)$df(i)}if(e=_$HY.dlq){_$HY.dlq=0;for(i in e)$dfl(i)}}function $dfs(e,c,d){(_$HY.sc=_$HY.sc||{})[e]=c,d&&((_$HY.sd=_$HY.sd||{})[e]=1)}function $dfg(e,g,i,k){if(!(g=_$HY.sg&&_$HY.sg[e]))return;for(i=0;i<g.length;i++)if(_$HY.sc&&_$HY.sc[g[i]]>0)return;for(i=0;i<g.length;i++)k=g[i],delete _$HY.sg[k],$df(k)}function $dfc(e){if(--_$HY.sc[e]<=0){delete _$HY.sc[e],_$HY.sg&&_$HY.sg[e]?$dfg(e):!(_$HY.sd&&_$HY.sd[e])&&$df(e);_$HY.sd&&delete _$HY.sd[e]}}function $dfj(e,i,n){for(i=0;i<e.length;i++)if(_$HY.sc&&_$HY.sc[e[i]]>0){for(n=0;n<e.length;n++)(_$HY.sg=_$HY.sg||{})[e[n]]=e;return}for(i=0;i<e.length;i++)$df(e[i])}`;
188
230
  function renderToString(code, options = {}) {
189
231
  const {
190
232
  renderId = "",
@@ -193,7 +235,7 @@ function renderToString(code, options = {}) {
193
235
  manifest
194
236
  } = options;
195
237
  let scripts = "";
196
- const serializer = createSerializer({
238
+ const serializer = createHydrationSerializer({
197
239
  scopeId: renderId,
198
240
  plugins: options.plugins,
199
241
  onData(script) {
@@ -219,16 +261,20 @@ function renderToString(code, options = {}) {
219
261
  }
220
262
  serializer.write(id, p);
221
263
  },
222
- registerAsset(type, url) {
264
+ registerAsset(type, value) {
265
+ if (type === "inline-style") {
266
+ tracking.registerInlineStyle(value);
267
+ return;
268
+ }
223
269
  if (tracking.currentBoundaryId && type === "style") {
224
270
  let styles = tracking.boundaryStyles.get(tracking.currentBoundaryId);
225
271
  if (!styles) {
226
272
  styles = new Set();
227
273
  tracking.boundaryStyles.set(tracking.currentBoundaryId, styles);
228
274
  }
229
- styles.add(url);
275
+ styles.add(value);
230
276
  }
231
- tracking.emittedAssets.add(url);
277
+ tracking.emittedAssets.add(value);
232
278
  }
233
279
  };
234
280
  applyAssetTracking(sharedConfig.context, tracking, manifest);
@@ -244,6 +290,7 @@ function renderToString(code, options = {}) {
244
290
  serializer.close();
245
291
  html = injectAssets(sharedConfig.context.assets, html);
246
292
  html = injectPreloadLinks(tracking.emittedAssets, html);
293
+ html = injectInlineStyles(tracking.inlineStyles, html, nonce);
247
294
  if (scripts.length) html = injectScripts(html, scripts, options.nonce);
248
295
  return html;
249
296
  }
@@ -282,7 +329,7 @@ function renderToStream(code, options = {}) {
282
329
  completed = true;
283
330
  if (firstFlushed) dispose();
284
331
  };
285
- const serializer = createSerializer({
332
+ const serializer = createHydrationSerializer({
286
333
  scopeId: options.renderId,
287
334
  plugins: options.plugins,
288
335
  onData: pushTask,
@@ -354,19 +401,27 @@ function renderToStream(code, options = {}) {
354
401
  async: true,
355
402
  assets: [],
356
403
  nonce,
357
- registerAsset(type, url) {
404
+ registerAsset(type, value) {
405
+ if (type === "inline-style") {
406
+ const entry = tracking.registerInlineStyle(value);
407
+ if (firstFlushed && !tracking.currentBoundaryId && !entry.emitted) {
408
+ entry.emitted = true;
409
+ buffer.write(renderInlineStyle(entry, nonce));
410
+ }
411
+ return;
412
+ }
358
413
  if (tracking.currentBoundaryId && type === "style") {
359
414
  let styles = tracking.boundaryStyles.get(tracking.currentBoundaryId);
360
415
  if (!styles) {
361
416
  styles = new Set();
362
417
  tracking.boundaryStyles.set(tracking.currentBoundaryId, styles);
363
418
  }
364
- styles.add(url);
419
+ styles.add(value);
365
420
  }
366
- if (!tracking.emittedAssets.has(url)) {
367
- tracking.emittedAssets.add(url);
421
+ if (!tracking.emittedAssets.has(value)) {
422
+ tracking.emittedAssets.add(value);
368
423
  if (firstFlushed && type === "module") {
369
- buffer.write(`<link rel="modulepreload" href="${url}">`);
424
+ buffer.write(`<link rel="modulepreload" href="${value}">`);
370
425
  }
371
426
  }
372
427
  },
@@ -450,10 +505,13 @@ function renderToStream(code, options = {}) {
450
505
  serializeFragmentAssets(key, tracking.boundaryModules, context);
451
506
  const styles = collectStreamStyles(key, tracking, headStyles);
452
507
  const deferActivation = !!revealGroup;
453
- if (styles.length) {
454
- emitTask(`$dfs("${key}",${styles.length},${deferActivation ? 1 : 0})`);
508
+ for (let i = 0; i < styles.inline.length; i++) {
509
+ buffer.write(renderInlineStyle(styles.inline[i], nonce));
510
+ }
511
+ if (styles.links.length) {
512
+ emitTask(`$dfs("${key}",${styles.links.length},${deferActivation ? 1 : 0})`);
455
513
  writeTasks();
456
- for (const url of styles) {
514
+ for (const url of styles.links) {
457
515
  buffer.write(`<link rel="stylesheet" href="${url}" onload="$dfc('${key}')" onerror="$dfc('${key}')">`);
458
516
  }
459
517
  buffer.write(`<template id="${key}">${value !== undefined ? value : " "}</template>`);
@@ -544,6 +602,7 @@ function renderToStream(code, options = {}) {
544
602
  if (url.endsWith(".css")) headStyles.add(url);
545
603
  }
546
604
  html = injectPreloadLinks(tracking.emittedAssets, html);
605
+ html = injectInlineStyles(tracking.inlineStyles, html, nonce);
547
606
  serializeRootAssets();
548
607
  if (tasks.length) html = injectScripts(html, tasks, nonce);
549
608
  buffer.write(html);
@@ -849,10 +908,11 @@ function ssrStyleProperty(name, value) {
849
908
  return value != null ? name + value : "";
850
909
  }
851
910
  function ssrElement(tag, props, children, needsId) {
911
+ const hk = needsId ? ssrHydrationKey() : "";
852
912
  if (props == null) props = {};else if (typeof props === "function") props = props();
853
913
  const skipChildren = VOID_ELEMENTS.test(tag);
854
914
  const keys = Object.keys(props);
855
- let result = `<${tag}${needsId ? ssrHydrationKey() : ""} `;
915
+ let result = `<${tag}${hk} `;
856
916
  for (let i = 0; i < keys.length; i++) {
857
917
  const prop = keys[i];
858
918
  if (ChildProperties.has(prop)) {
@@ -897,7 +957,10 @@ function escape(s, attr) {
897
957
  for (let i = 0; i < s.length; i++) s[i] = escape(s[i]);
898
958
  return s;
899
959
  }
900
- if (attr && t === "boolean") return s;
960
+ if (attr) {
961
+ if (s == null || t === "boolean" || t === "number") return s;
962
+ return escape(String(s), attr);
963
+ }
901
964
  return s;
902
965
  }
903
966
  const delimCode = attr ? 34 : 60;
@@ -1033,14 +1096,48 @@ function propagateBoundaryStyles(childKey, parentKey, tracking) {
1033
1096
  }
1034
1097
  function collectStreamStyles(key, tracking, headStyles) {
1035
1098
  const styles = tracking.getBoundaryStyles(key);
1036
- if (!styles) return [];
1037
- const result = [];
1038
- for (const url of styles) {
1039
- if (!headStyles || !headStyles.has(url)) {
1040
- result.push(url);
1099
+ const links = [];
1100
+ const inline = [];
1101
+ if (!styles) return {
1102
+ links,
1103
+ inline
1104
+ };
1105
+ for (const entry of styles) {
1106
+ if (typeof entry === "string") {
1107
+ if (!headStyles || !headStyles.has(entry)) links.push(entry);
1108
+ } else if (!entry.emitted) {
1109
+ entry.emitted = true;
1110
+ inline.push(entry);
1041
1111
  }
1042
1112
  }
1043
- return result;
1113
+ return {
1114
+ links,
1115
+ inline
1116
+ };
1117
+ }
1118
+ function escapeStyleContent(content) {
1119
+ return content.replace(/<\/(style)/gi, "<\\/$1");
1120
+ }
1121
+ function renderInlineStyle(entry, nonce) {
1122
+ let attrs = "";
1123
+ if (entry.attrs) {
1124
+ for (const name in entry.attrs) {
1125
+ attrs += ` ${name}="${escape(String(entry.attrs[name]), true)}"`;
1126
+ }
1127
+ }
1128
+ return `<style${nonce ? ` nonce="${nonce}"` : ""} data-asset="${escape(entry.id, true)}"${attrs}>${escapeStyleContent(entry.content)}</style>`;
1129
+ }
1130
+ function injectInlineStyles(inlineStyles, html, nonce) {
1131
+ if (!inlineStyles.size) return html;
1132
+ const index = html.indexOf("</head>");
1133
+ if (index === -1) return html;
1134
+ let out = "";
1135
+ for (const entry of inlineStyles.values()) {
1136
+ if (entry.emitted) continue;
1137
+ entry.emitted = true;
1138
+ out += renderInlineStyle(entry, nonce);
1139
+ }
1140
+ return out ? html.slice(0, index) + out + html.slice(index) : html;
1044
1141
  }
1045
1142
  function injectScripts(html, scripts, nonce) {
1046
1143
  const tag = `<script${nonce ? ` nonce="${nonce}"` : ""}>${scripts}</script>`;
@@ -1226,7 +1323,9 @@ function Dynamic(props) {
1226
1323
  return createComponent(Comp, omit(props, "component"));
1227
1324
  }
1228
1325
  function Portal(props) {
1229
- throw new Error("Portal is not supported on the server");
1326
+ const o = getOwner();
1327
+ if (o?.id != null) getNextChildId(o);
1328
+ return undefined;
1230
1329
  }
1231
1330
 
1232
- export { Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, SVGElements, VoidElements, notSup as addEvent, applyRef, notSup as assign, notSup as className, notSup as delegateEvents, dynamic, notSup as dynamicProperty, effect, escape, generateHydrationScript, getAssets, notSup as getDelegatedRoot, getHydrationKey, notSup as getNextElement, notSup as getNextMarker, notSup as getNextMatch, getRequestEvent, notSup as hydrate, notSup as insert, isDev, isServer, memo, notSup as ref, notSup as registerDelegatedContainer, notSup as registerDelegatedRoot, notSup as render, renderToStream, renderToString, renderToStringAsync, notSup as runHydrationEvents, notSup as setAttribute, notSup as setAttributeNS, notSup as setProperty, notSup as setStyleProperty, notSup as spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, notSup as style, notSup as template, notSup as unregisterDelegatedContainer, notSup as unregisterDelegatedRoot, useAssets };
1331
+ export { Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, SVGElements, VoidElements, notSup as acquireAsset, notSup as addEvent, applyRef, notSup as assign, notSup as className, notSup as delegateEvents, dynamic, notSup as dynamicProperty, effect, escape, generateHydrationScript, getAssets, notSup as getDelegatedRoot, getHydrationKey, notSup as getNextElement, notSup as getNextMarker, notSup as getNextMatch, getRequestEvent, notSup as hydrate, notSup as insert, isDev, isServer, memo, notSup as ref, notSup as registerDelegatedContainer, notSup as registerDelegatedRoot, notSup as render, renderToStream, renderToString, renderToStringAsync, notSup as runHydrationEvents, notSup as setAttribute, notSup as setAttributeNS, notSup as setProperty, notSup as setStyleProperty, notSup as spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, notSup as style, notSup as template, notSup as unregisterDelegatedContainer, notSup as unregisterDelegatedRoot, useAssets };
package/dist/web.cjs CHANGED
@@ -504,22 +504,117 @@ function assign(node, props, skipChildren, prevProps = {}, skipRef = false) {
504
504
  prevProps[prop] = assignProp(node, prop, props[prop], prevProps[prop], skipRef, nodeName);
505
505
  }
506
506
  }
507
+ const ASSET_REMOVAL_GRACE = 100;
508
+ const assetRegistry = new Map();
509
+ function assetEntryKey(descriptor) {
510
+ if (descriptor.policy === "exclusive") return "x|" + descriptor.key;
511
+ return descriptor.type === "inline-style" ? "i|" + descriptor.id : descriptor.type + "|" + descriptor.href;
512
+ }
513
+ function findAssetElement(selector, attr, value) {
514
+ const nodes = document.querySelectorAll(selector);
515
+ for (let i = 0; i < nodes.length; i++) {
516
+ if (nodes[i].getAttribute(attr) === value) return nodes[i];
517
+ }
518
+ return null;
519
+ }
520
+ function mountAssetElement(descriptor) {
521
+ let el;
522
+ if (descriptor.type === "inline-style") {
523
+ el = findAssetElement("style[data-asset]", "data-asset", descriptor.id);
524
+ if (!el) {
525
+ el = document.createElement("style");
526
+ el.setAttribute("data-asset", descriptor.id);
527
+ el.textContent = descriptor.content || "";
528
+ }
529
+ } else {
530
+ const rel = descriptor.type === "module" ? "modulepreload" : "stylesheet";
531
+ el = findAssetElement(`link[rel="${rel}"]`, "href", descriptor.href);
532
+ if (!el) {
533
+ el = document.createElement("link");
534
+ el.rel = rel;
535
+ el.href = descriptor.href;
536
+ }
537
+ }
538
+ if (descriptor.attrs) {
539
+ for (const name in descriptor.attrs) el.setAttribute(name, descriptor.attrs[name]);
540
+ }
541
+ if (!el.isConnected) document.head.appendChild(el);
542
+ return el;
543
+ }
544
+ function acquireAsset(descriptor) {
545
+ const key = assetEntryKey(descriptor);
546
+ let entry = assetRegistry.get(key);
547
+ if (descriptor.policy === "exclusive") {
548
+ if (!entry) {
549
+ entry = {
550
+ original: descriptor.get(),
551
+ set: descriptor.set,
552
+ writers: []
553
+ };
554
+ assetRegistry.set(key, entry);
555
+ }
556
+ const writer = {
557
+ value: descriptor.value
558
+ };
559
+ entry.writers.push(writer);
560
+ entry.set(writer.value);
561
+ let released = false;
562
+ return () => {
563
+ if (released) return;
564
+ released = true;
565
+ const index = entry.writers.indexOf(writer);
566
+ const wasTop = index === entry.writers.length - 1;
567
+ entry.writers.splice(index, 1);
568
+ if (!wasTop) return;
569
+ if (entry.writers.length) {
570
+ entry.set(entry.writers[entry.writers.length - 1].value);
571
+ } else {
572
+ entry.set(entry.original);
573
+ assetRegistry.delete(key);
574
+ }
575
+ };
576
+ }
577
+ if (!entry) {
578
+ entry = {
579
+ count: 0,
580
+ element: null,
581
+ timer: null
582
+ };
583
+ assetRegistry.set(key, entry);
584
+ }
585
+ if (entry.timer) {
586
+ clearTimeout(entry.timer);
587
+ entry.timer = null;
588
+ }
589
+ entry.count++;
590
+ if (!entry.element || !entry.element.isConnected) entry.element = mountAssetElement(descriptor);
591
+ let released = false;
592
+ return () => {
593
+ if (released) return;
594
+ released = true;
595
+ if (--entry.count > 0) return;
596
+ entry.timer = setTimeout(() => {
597
+ assetRegistry.delete(key);
598
+ entry.element && entry.element.remove();
599
+ }, ASSET_REMOVAL_GRACE);
600
+ };
601
+ }
507
602
  function loadModuleAssets(mapping) {
508
603
  const hy = globalThis._$HY;
509
604
  if (!hy) return;
510
605
  const pending = [];
511
- for (const moduleUrl in mapping) {
512
- if (hy.modules[moduleUrl]) continue;
513
- const entryUrl = mapping[moduleUrl];
514
- if (!hy.loading[moduleUrl]) {
515
- hy.loading[moduleUrl] = import(entryUrl).then(mod => {
516
- hy.modules[moduleUrl] = mod;
606
+ for (const key in mapping) {
607
+ if (hy.modules[key]) continue;
608
+ const entryUrl = mapping[key];
609
+ if (!hy.loading[key]) {
610
+ hy.loading[key] = import(entryUrl).then(mod => {
611
+ hy.modules[key] = mod;
517
612
  }, err => {
518
- delete hy.loading[moduleUrl];
613
+ delete hy.loading[key];
519
614
  throw err;
520
615
  });
521
616
  }
522
- pending.push(hy.loading[moduleUrl]);
617
+ pending.push(hy.loading[key]);
523
618
  }
524
619
  return pending.length ? Promise.all(pending).then(() => {}) : undefined;
525
620
  }
@@ -806,7 +901,12 @@ function insertExpression(parent, value, current, marker) {
806
901
  const tc = typeof current;
807
902
  if (tc === "string" || tc === "number") {
808
903
  parent.firstChild.data = value;
809
- } else parent.textContent = value;
904
+ } else {
905
+ if (ownsAllChildren(parent, current)) parent.textContent = value;else {
906
+ removeOwnedChildren(parent, current);
907
+ parent.insertBefore(document.createTextNode(value), parent.firstChild);
908
+ }
909
+ }
810
910
  } else if (value === undefined) {
811
911
  cleanChildren(parent, current, marker);
812
912
  } else if (value.nodeType) {
@@ -829,7 +929,7 @@ function insertExpression(parent, value, current, marker) {
829
929
  appendNodes(parent, value, marker);
830
930
  } else reconcileArrays(parent, current, value, marker);
831
931
  } else {
832
- current && cleanChildren(parent);
932
+ current && cleanChildren(parent, current);
833
933
  appendNodes(parent, value);
834
934
  }
835
935
  } else ;
@@ -869,8 +969,34 @@ function appendNodes(parent, array, marker = null) {
869
969
  if (marker) n[$$SLOT] = marker;
870
970
  }
871
971
  }
972
+ function ownsAllChildren(parent, current) {
973
+ if (current == null) return true;
974
+ if (Array.isArray(current)) {
975
+ return current.length ? parent.firstChild === current[0] && parent.lastChild === current[current.length - 1] : parent.firstChild === null;
976
+ }
977
+ if (current === "") return parent.firstChild === null;
978
+ if (current.nodeType) return parent.firstChild === current && parent.lastChild === current;
979
+ const first = parent.firstChild;
980
+ return first !== null && first.nodeType === 3 && parent.lastChild === first;
981
+ }
982
+ function removeOwnedChildren(parent, current) {
983
+ if (Array.isArray(current)) {
984
+ for (let i = 0; i < current.length; i++) {
985
+ const el = current[i];
986
+ if (el.parentNode === parent) el.remove();
987
+ }
988
+ } else if (current.nodeType) {
989
+ if (current.parentNode === parent) current.remove();
990
+ } else {
991
+ const first = parent.firstChild;
992
+ if (first && first.nodeType === 3) first.remove();
993
+ }
994
+ }
872
995
  function cleanChildren(parent, current, marker, replacement) {
873
- if (marker === undefined) return parent.textContent = "";
996
+ if (marker === undefined) {
997
+ if (ownsAllChildren(parent, current)) return parent.textContent = "";
998
+ return removeOwnedChildren(parent, current);
999
+ }
874
1000
  if (current.length) {
875
1001
  let inserted = false;
876
1002
  for (let i = current.length - 1; i >= 0; i--) {
@@ -941,11 +1067,16 @@ const hydrate = (...args) => {
941
1067
  return hydrate$1(...args);
942
1068
  };
943
1069
  function Portal(props) {
1070
+ return solidJs.runWithOwner(solidJs.createOwner(), () => portalImpl(props));
1071
+ }
1072
+ function portalImpl(props) {
944
1073
  const treeMarker = document.createTextNode(""),
945
1074
  startMarker = document.createTextNode(""),
946
1075
  endMarker = document.createTextNode(""),
947
1076
  mount = () => props.mount || document.body,
948
- content = solidJs.createMemo(() => [startMarker, props.children]);
1077
+ content = solidJs.createMemo(() => [startMarker, props.children], {
1078
+ ssrSource: "client"
1079
+ });
949
1080
  solidJs.createRenderEffect(
950
1081
  () => [mount(), content(), solidJs.getOwner()], ([, c, owner]) => {
951
1082
  const m = solidJs.untrack(mount);
@@ -966,8 +1097,10 @@ function Portal(props) {
966
1097
  c = n;
967
1098
  }
968
1099
  };
969
- }, {
970
- schedule: true
1100
+ },
1101
+ {
1102
+ schedule: true,
1103
+ ssrSource: "client"
971
1104
  });
972
1105
  solidJs.createEffect(mount, () => {
973
1106
  const m = solidJs.untrack(mount);
@@ -975,6 +1108,11 @@ function Portal(props) {
975
1108
  if (!ownerRoot || ownerRoot.contains(m)) return;
976
1109
  registerDelegatedContainer(m, ownerRoot);
977
1110
  return () => unregisterDelegatedContainer(m, ownerRoot);
1111
+ }, {
1112
+ ssrSource: "client"
1113
+ });
1114
+ if (solidJs.sharedConfig.hydrating) return solidJs.createMemo(() => treeMarker, {
1115
+ ssrSource: "client"
978
1116
  });
979
1117
  return treeMarker;
980
1118
  }
@@ -1072,6 +1210,7 @@ exports.RawTextElements = RawTextElements;
1072
1210
  exports.RequestContext = RequestContext;
1073
1211
  exports.SVGElements = SVGElements;
1074
1212
  exports.VoidElements = VoidElements;
1213
+ exports.acquireAsset = acquireAsset;
1075
1214
  exports.addEvent = addEvent;
1076
1215
  exports.applyRef = applyRef;
1077
1216
  exports.assign = assign;