@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/dev.cjs CHANGED
@@ -509,22 +509,117 @@ function assign(node, props, skipChildren, prevProps = {}, skipRef = false) {
509
509
  prevProps[prop] = assignProp(node, prop, props[prop], prevProps[prop], skipRef, nodeName);
510
510
  }
511
511
  }
512
+ const ASSET_REMOVAL_GRACE = 100;
513
+ const assetRegistry = new Map();
514
+ function assetEntryKey(descriptor) {
515
+ if (descriptor.policy === "exclusive") return "x|" + descriptor.key;
516
+ return descriptor.type === "inline-style" ? "i|" + descriptor.id : descriptor.type + "|" + descriptor.href;
517
+ }
518
+ function findAssetElement(selector, attr, value) {
519
+ const nodes = document.querySelectorAll(selector);
520
+ for (let i = 0; i < nodes.length; i++) {
521
+ if (nodes[i].getAttribute(attr) === value) return nodes[i];
522
+ }
523
+ return null;
524
+ }
525
+ function mountAssetElement(descriptor) {
526
+ let el;
527
+ if (descriptor.type === "inline-style") {
528
+ el = findAssetElement("style[data-asset]", "data-asset", descriptor.id);
529
+ if (!el) {
530
+ el = document.createElement("style");
531
+ el.setAttribute("data-asset", descriptor.id);
532
+ el.textContent = descriptor.content || "";
533
+ }
534
+ } else {
535
+ const rel = descriptor.type === "module" ? "modulepreload" : "stylesheet";
536
+ el = findAssetElement(`link[rel="${rel}"]`, "href", descriptor.href);
537
+ if (!el) {
538
+ el = document.createElement("link");
539
+ el.rel = rel;
540
+ el.href = descriptor.href;
541
+ }
542
+ }
543
+ if (descriptor.attrs) {
544
+ for (const name in descriptor.attrs) el.setAttribute(name, descriptor.attrs[name]);
545
+ }
546
+ if (!el.isConnected) document.head.appendChild(el);
547
+ return el;
548
+ }
549
+ function acquireAsset(descriptor) {
550
+ const key = assetEntryKey(descriptor);
551
+ let entry = assetRegistry.get(key);
552
+ if (descriptor.policy === "exclusive") {
553
+ if (!entry) {
554
+ entry = {
555
+ original: descriptor.get(),
556
+ set: descriptor.set,
557
+ writers: []
558
+ };
559
+ assetRegistry.set(key, entry);
560
+ }
561
+ const writer = {
562
+ value: descriptor.value
563
+ };
564
+ entry.writers.push(writer);
565
+ entry.set(writer.value);
566
+ let released = false;
567
+ return () => {
568
+ if (released) return;
569
+ released = true;
570
+ const index = entry.writers.indexOf(writer);
571
+ const wasTop = index === entry.writers.length - 1;
572
+ entry.writers.splice(index, 1);
573
+ if (!wasTop) return;
574
+ if (entry.writers.length) {
575
+ entry.set(entry.writers[entry.writers.length - 1].value);
576
+ } else {
577
+ entry.set(entry.original);
578
+ assetRegistry.delete(key);
579
+ }
580
+ };
581
+ }
582
+ if (!entry) {
583
+ entry = {
584
+ count: 0,
585
+ element: null,
586
+ timer: null
587
+ };
588
+ assetRegistry.set(key, entry);
589
+ }
590
+ if (entry.timer) {
591
+ clearTimeout(entry.timer);
592
+ entry.timer = null;
593
+ }
594
+ entry.count++;
595
+ if (!entry.element || !entry.element.isConnected) entry.element = mountAssetElement(descriptor);
596
+ let released = false;
597
+ return () => {
598
+ if (released) return;
599
+ released = true;
600
+ if (--entry.count > 0) return;
601
+ entry.timer = setTimeout(() => {
602
+ assetRegistry.delete(key);
603
+ entry.element && entry.element.remove();
604
+ }, ASSET_REMOVAL_GRACE);
605
+ };
606
+ }
512
607
  function loadModuleAssets(mapping) {
513
608
  const hy = globalThis._$HY;
514
609
  if (!hy) return;
515
610
  const pending = [];
516
- for (const moduleUrl in mapping) {
517
- if (hy.modules[moduleUrl]) continue;
518
- const entryUrl = mapping[moduleUrl];
519
- if (!hy.loading[moduleUrl]) {
520
- hy.loading[moduleUrl] = import(entryUrl).then(mod => {
521
- hy.modules[moduleUrl] = mod;
611
+ for (const key in mapping) {
612
+ if (hy.modules[key]) continue;
613
+ const entryUrl = mapping[key];
614
+ if (!hy.loading[key]) {
615
+ hy.loading[key] = import(entryUrl).then(mod => {
616
+ hy.modules[key] = mod;
522
617
  }, err => {
523
- delete hy.loading[moduleUrl];
618
+ delete hy.loading[key];
524
619
  throw err;
525
620
  });
526
621
  }
527
- pending.push(hy.loading[moduleUrl]);
622
+ pending.push(hy.loading[key]);
528
623
  }
529
624
  return pending.length ? Promise.all(pending).then(() => {}) : undefined;
530
625
  }
@@ -863,7 +958,12 @@ function insertExpression(parent, value, current, marker) {
863
958
  const tc = typeof current;
864
959
  if (tc === "string" || tc === "number") {
865
960
  parent.firstChild.data = value;
866
- } else parent.textContent = value;
961
+ } else {
962
+ if (ownsAllChildren(parent, current)) parent.textContent = value;else {
963
+ removeOwnedChildren(parent, current);
964
+ parent.insertBefore(document.createTextNode(value), parent.firstChild);
965
+ }
966
+ }
867
967
  } else if (value === undefined) {
868
968
  cleanChildren(parent, current, marker);
869
969
  } else if (value.nodeType) {
@@ -886,7 +986,7 @@ function insertExpression(parent, value, current, marker) {
886
986
  appendNodes(parent, value, marker);
887
987
  } else reconcileArrays(parent, current, value, marker);
888
988
  } else {
889
- current && cleanChildren(parent);
989
+ current && cleanChildren(parent, current);
890
990
  appendNodes(parent, value);
891
991
  }
892
992
  } else console.warn(`Unrecognized value. Skipped inserting`, value);
@@ -926,8 +1026,34 @@ function appendNodes(parent, array, marker = null) {
926
1026
  if (marker) n[$$SLOT] = marker;
927
1027
  }
928
1028
  }
1029
+ function ownsAllChildren(parent, current) {
1030
+ if (current == null) return true;
1031
+ if (Array.isArray(current)) {
1032
+ return current.length ? parent.firstChild === current[0] && parent.lastChild === current[current.length - 1] : parent.firstChild === null;
1033
+ }
1034
+ if (current === "") return parent.firstChild === null;
1035
+ if (current.nodeType) return parent.firstChild === current && parent.lastChild === current;
1036
+ const first = parent.firstChild;
1037
+ return first !== null && first.nodeType === 3 && parent.lastChild === first;
1038
+ }
1039
+ function removeOwnedChildren(parent, current) {
1040
+ if (Array.isArray(current)) {
1041
+ for (let i = 0; i < current.length; i++) {
1042
+ const el = current[i];
1043
+ if (el.parentNode === parent) el.remove();
1044
+ }
1045
+ } else if (current.nodeType) {
1046
+ if (current.parentNode === parent) current.remove();
1047
+ } else {
1048
+ const first = parent.firstChild;
1049
+ if (first && first.nodeType === 3) first.remove();
1050
+ }
1051
+ }
929
1052
  function cleanChildren(parent, current, marker, replacement) {
930
- if (marker === undefined) return parent.textContent = "";
1053
+ if (marker === undefined) {
1054
+ if (ownsAllChildren(parent, current)) return parent.textContent = "";
1055
+ return removeOwnedChildren(parent, current);
1056
+ }
931
1057
  if (current.length) {
932
1058
  let inserted = false;
933
1059
  for (let i = current.length - 1; i >= 0; i--) {
@@ -1000,11 +1126,16 @@ const hydrate = (...args) => {
1000
1126
  return hydrate$1(...args);
1001
1127
  };
1002
1128
  function Portal(props) {
1129
+ return solidJs.runWithOwner(solidJs.createOwner(), () => portalImpl(props));
1130
+ }
1131
+ function portalImpl(props) {
1003
1132
  const treeMarker = document.createTextNode(""),
1004
1133
  startMarker = document.createTextNode(""),
1005
1134
  endMarker = document.createTextNode(""),
1006
1135
  mount = () => props.mount || document.body,
1007
- content = solidJs.createMemo(() => [startMarker, props.children]);
1136
+ content = solidJs.createMemo(() => [startMarker, props.children], {
1137
+ ssrSource: "client"
1138
+ });
1008
1139
  solidJs.createRenderEffect(
1009
1140
  () => [mount(), content(), solidJs.getOwner()], ([, c, owner]) => {
1010
1141
  const m = solidJs.untrack(mount);
@@ -1025,8 +1156,10 @@ function Portal(props) {
1025
1156
  c = n;
1026
1157
  }
1027
1158
  };
1028
- }, {
1029
- schedule: true
1159
+ },
1160
+ {
1161
+ schedule: true,
1162
+ ssrSource: "client"
1030
1163
  });
1031
1164
  solidJs.createEffect(mount, () => {
1032
1165
  const m = solidJs.untrack(mount);
@@ -1034,6 +1167,11 @@ function Portal(props) {
1034
1167
  if (!ownerRoot || ownerRoot.contains(m)) return;
1035
1168
  registerDelegatedContainer(m, ownerRoot);
1036
1169
  return () => unregisterDelegatedContainer(m, ownerRoot);
1170
+ }, {
1171
+ ssrSource: "client"
1172
+ });
1173
+ if (solidJs.sharedConfig.hydrating) return solidJs.createMemo(() => treeMarker, {
1174
+ ssrSource: "client"
1037
1175
  });
1038
1176
  return treeMarker;
1039
1177
  }
@@ -1134,6 +1272,7 @@ exports.RawTextElements = RawTextElements;
1134
1272
  exports.RequestContext = RequestContext;
1135
1273
  exports.SVGElements = SVGElements;
1136
1274
  exports.VoidElements = VoidElements;
1275
+ exports.acquireAsset = acquireAsset;
1137
1276
  exports.addEvent = addEvent;
1138
1277
  exports.applyRef = applyRef;
1139
1278
  exports.assign = assign;
package/dist/dev.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createRenderEffect, createMemo, sharedConfig, untrack, runWithOwner, flatten, createRoot, merge, createComponent, omit, getOwner, createEffect, $DEVCOMP, enableHydration, enforceLoadingBoundary, flush } from 'solid-js';
1
+ import { createRenderEffect, createMemo, sharedConfig, untrack, runWithOwner, flatten, createRoot, merge, createComponent, omit, createOwner, $DEVCOMP, enableHydration, enforceLoadingBoundary, 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 = {
@@ -508,22 +508,117 @@ function assign(node, props, skipChildren, prevProps = {}, skipRef = false) {
508
508
  prevProps[prop] = assignProp(node, prop, props[prop], prevProps[prop], skipRef, nodeName);
509
509
  }
510
510
  }
511
+ const ASSET_REMOVAL_GRACE = 100;
512
+ const assetRegistry = new Map();
513
+ function assetEntryKey(descriptor) {
514
+ if (descriptor.policy === "exclusive") return "x|" + descriptor.key;
515
+ return descriptor.type === "inline-style" ? "i|" + descriptor.id : descriptor.type + "|" + descriptor.href;
516
+ }
517
+ function findAssetElement(selector, attr, value) {
518
+ const nodes = document.querySelectorAll(selector);
519
+ for (let i = 0; i < nodes.length; i++) {
520
+ if (nodes[i].getAttribute(attr) === value) return nodes[i];
521
+ }
522
+ return null;
523
+ }
524
+ function mountAssetElement(descriptor) {
525
+ let el;
526
+ if (descriptor.type === "inline-style") {
527
+ el = findAssetElement("style[data-asset]", "data-asset", descriptor.id);
528
+ if (!el) {
529
+ el = document.createElement("style");
530
+ el.setAttribute("data-asset", descriptor.id);
531
+ el.textContent = descriptor.content || "";
532
+ }
533
+ } else {
534
+ const rel = descriptor.type === "module" ? "modulepreload" : "stylesheet";
535
+ el = findAssetElement(`link[rel="${rel}"]`, "href", descriptor.href);
536
+ if (!el) {
537
+ el = document.createElement("link");
538
+ el.rel = rel;
539
+ el.href = descriptor.href;
540
+ }
541
+ }
542
+ if (descriptor.attrs) {
543
+ for (const name in descriptor.attrs) el.setAttribute(name, descriptor.attrs[name]);
544
+ }
545
+ if (!el.isConnected) document.head.appendChild(el);
546
+ return el;
547
+ }
548
+ function acquireAsset(descriptor) {
549
+ const key = assetEntryKey(descriptor);
550
+ let entry = assetRegistry.get(key);
551
+ if (descriptor.policy === "exclusive") {
552
+ if (!entry) {
553
+ entry = {
554
+ original: descriptor.get(),
555
+ set: descriptor.set,
556
+ writers: []
557
+ };
558
+ assetRegistry.set(key, entry);
559
+ }
560
+ const writer = {
561
+ value: descriptor.value
562
+ };
563
+ entry.writers.push(writer);
564
+ entry.set(writer.value);
565
+ let released = false;
566
+ return () => {
567
+ if (released) return;
568
+ released = true;
569
+ const index = entry.writers.indexOf(writer);
570
+ const wasTop = index === entry.writers.length - 1;
571
+ entry.writers.splice(index, 1);
572
+ if (!wasTop) return;
573
+ if (entry.writers.length) {
574
+ entry.set(entry.writers[entry.writers.length - 1].value);
575
+ } else {
576
+ entry.set(entry.original);
577
+ assetRegistry.delete(key);
578
+ }
579
+ };
580
+ }
581
+ if (!entry) {
582
+ entry = {
583
+ count: 0,
584
+ element: null,
585
+ timer: null
586
+ };
587
+ assetRegistry.set(key, entry);
588
+ }
589
+ if (entry.timer) {
590
+ clearTimeout(entry.timer);
591
+ entry.timer = null;
592
+ }
593
+ entry.count++;
594
+ if (!entry.element || !entry.element.isConnected) entry.element = mountAssetElement(descriptor);
595
+ let released = false;
596
+ return () => {
597
+ if (released) return;
598
+ released = true;
599
+ if (--entry.count > 0) return;
600
+ entry.timer = setTimeout(() => {
601
+ assetRegistry.delete(key);
602
+ entry.element && entry.element.remove();
603
+ }, ASSET_REMOVAL_GRACE);
604
+ };
605
+ }
511
606
  function loadModuleAssets(mapping) {
512
607
  const hy = globalThis._$HY;
513
608
  if (!hy) return;
514
609
  const pending = [];
515
- for (const moduleUrl in mapping) {
516
- if (hy.modules[moduleUrl]) continue;
517
- const entryUrl = mapping[moduleUrl];
518
- if (!hy.loading[moduleUrl]) {
519
- hy.loading[moduleUrl] = import(entryUrl).then(mod => {
520
- hy.modules[moduleUrl] = mod;
610
+ for (const key in mapping) {
611
+ if (hy.modules[key]) continue;
612
+ const entryUrl = mapping[key];
613
+ if (!hy.loading[key]) {
614
+ hy.loading[key] = import(entryUrl).then(mod => {
615
+ hy.modules[key] = mod;
521
616
  }, err => {
522
- delete hy.loading[moduleUrl];
617
+ delete hy.loading[key];
523
618
  throw err;
524
619
  });
525
620
  }
526
- pending.push(hy.loading[moduleUrl]);
621
+ pending.push(hy.loading[key]);
527
622
  }
528
623
  return pending.length ? Promise.all(pending).then(() => {}) : undefined;
529
624
  }
@@ -862,7 +957,12 @@ function insertExpression(parent, value, current, marker) {
862
957
  const tc = typeof current;
863
958
  if (tc === "string" || tc === "number") {
864
959
  parent.firstChild.data = value;
865
- } else parent.textContent = value;
960
+ } else {
961
+ if (ownsAllChildren(parent, current)) parent.textContent = value;else {
962
+ removeOwnedChildren(parent, current);
963
+ parent.insertBefore(document.createTextNode(value), parent.firstChild);
964
+ }
965
+ }
866
966
  } else if (value === undefined) {
867
967
  cleanChildren(parent, current, marker);
868
968
  } else if (value.nodeType) {
@@ -885,7 +985,7 @@ function insertExpression(parent, value, current, marker) {
885
985
  appendNodes(parent, value, marker);
886
986
  } else reconcileArrays(parent, current, value, marker);
887
987
  } else {
888
- current && cleanChildren(parent);
988
+ current && cleanChildren(parent, current);
889
989
  appendNodes(parent, value);
890
990
  }
891
991
  } else console.warn(`Unrecognized value. Skipped inserting`, value);
@@ -925,8 +1025,34 @@ function appendNodes(parent, array, marker = null) {
925
1025
  if (marker) n[$$SLOT] = marker;
926
1026
  }
927
1027
  }
1028
+ function ownsAllChildren(parent, current) {
1029
+ if (current == null) return true;
1030
+ if (Array.isArray(current)) {
1031
+ return current.length ? parent.firstChild === current[0] && parent.lastChild === current[current.length - 1] : parent.firstChild === null;
1032
+ }
1033
+ if (current === "") return parent.firstChild === null;
1034
+ if (current.nodeType) return parent.firstChild === current && parent.lastChild === current;
1035
+ const first = parent.firstChild;
1036
+ return first !== null && first.nodeType === 3 && parent.lastChild === first;
1037
+ }
1038
+ function removeOwnedChildren(parent, current) {
1039
+ if (Array.isArray(current)) {
1040
+ for (let i = 0; i < current.length; i++) {
1041
+ const el = current[i];
1042
+ if (el.parentNode === parent) el.remove();
1043
+ }
1044
+ } else if (current.nodeType) {
1045
+ if (current.parentNode === parent) current.remove();
1046
+ } else {
1047
+ const first = parent.firstChild;
1048
+ if (first && first.nodeType === 3) first.remove();
1049
+ }
1050
+ }
928
1051
  function cleanChildren(parent, current, marker, replacement) {
929
- if (marker === undefined) return parent.textContent = "";
1052
+ if (marker === undefined) {
1053
+ if (ownsAllChildren(parent, current)) return parent.textContent = "";
1054
+ return removeOwnedChildren(parent, current);
1055
+ }
930
1056
  if (current.length) {
931
1057
  let inserted = false;
932
1058
  for (let i = current.length - 1; i >= 0; i--) {
@@ -999,11 +1125,16 @@ const hydrate = (...args) => {
999
1125
  return hydrate$1(...args);
1000
1126
  };
1001
1127
  function Portal(props) {
1128
+ return runWithOwner(createOwner(), () => portalImpl(props));
1129
+ }
1130
+ function portalImpl(props) {
1002
1131
  const treeMarker = document.createTextNode(""),
1003
1132
  startMarker = document.createTextNode(""),
1004
1133
  endMarker = document.createTextNode(""),
1005
1134
  mount = () => props.mount || document.body,
1006
- content = createMemo(() => [startMarker, props.children]);
1135
+ content = createMemo(() => [startMarker, props.children], {
1136
+ ssrSource: "client"
1137
+ });
1007
1138
  createRenderEffect(
1008
1139
  () => [mount(), content(), getOwner()], ([, c, owner]) => {
1009
1140
  const m = untrack(mount);
@@ -1024,8 +1155,10 @@ function Portal(props) {
1024
1155
  c = n;
1025
1156
  }
1026
1157
  };
1027
- }, {
1028
- schedule: true
1158
+ },
1159
+ {
1160
+ schedule: true,
1161
+ ssrSource: "client"
1029
1162
  });
1030
1163
  createEffect(mount, () => {
1031
1164
  const m = untrack(mount);
@@ -1033,6 +1166,11 @@ function Portal(props) {
1033
1166
  if (!ownerRoot || ownerRoot.contains(m)) return;
1034
1167
  registerDelegatedContainer(m, ownerRoot);
1035
1168
  return () => unregisterDelegatedContainer(m, ownerRoot);
1169
+ }, {
1170
+ ssrSource: "client"
1171
+ });
1172
+ if (sharedConfig.hydrating) return createMemo(() => treeMarker, {
1173
+ ssrSource: "client"
1036
1174
  });
1037
1175
  return treeMarker;
1038
1176
  }
@@ -1067,4 +1205,4 @@ function createElement(tagName, is = undefined) {
1067
1205
  });
1068
1206
  }
1069
1207
 
1070
- 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 };
1208
+ 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 };