@solidjs/web 2.0.0-beta.15 → 2.0.0-beta.17

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
@@ -60,9 +60,9 @@ const syncOptions = {
60
60
  sync: true
61
61
  };
62
62
  const effect = (fn, effectFn, options) => solidJs.createRenderEffect(fn, effectFn, options ? {
63
- transparent: true,
64
63
  sync: true,
65
- ...options
64
+ ...options,
65
+ transparent: !options.scope
66
66
  } : transparentOptions);
67
67
  const memo = fn => solidJs.createMemo(() => fn(), syncOptions);
68
68
 
@@ -335,20 +335,41 @@ function addEvent(node, name, handler, delegate) {
335
335
  }
336
336
  function style(node, value, prev) {
337
337
  if (!value) {
338
- if (prev) setAttribute(node, "style");
338
+ if (prev || node._$styles) {
339
+ setAttribute(node, "style");
340
+ node._$styles = undefined;
341
+ }
339
342
  return;
340
343
  }
341
344
  const nodeStyle = node.style;
342
- if (typeof value === "string") return nodeStyle.cssText = value;
343
- typeof prev === "string" && (nodeStyle.cssText = prev = undefined);
344
- prev || (prev = {});
345
+ if (typeof value === "string") {
346
+ node._$styles = undefined;
347
+ return nodeStyle.cssText = value;
348
+ }
349
+ if (typeof prev === "string") {
350
+ nodeStyle.cssText = "";
351
+ prev = undefined;
352
+ }
353
+ let applied = node._$styles;
354
+ if (!applied) {
355
+ applied = node._$styles = prev ? {
356
+ ...prev
357
+ } : {};
358
+ }
345
359
  let v, s;
360
+ for (s in applied) {
361
+ if (value[s] == null) {
362
+ nodeStyle.removeProperty(s);
363
+ delete applied[s];
364
+ }
365
+ }
346
366
  for (s in value) {
347
367
  v = value[s];
348
- if (v !== prev[s]) nodeStyle.setProperty(s, v);
349
- delete prev[s];
368
+ if (v != null && v !== applied[s]) {
369
+ nodeStyle.setProperty(s, v);
370
+ applied[s] = v;
371
+ }
350
372
  }
351
- for (s in prev) value[s] == null && nodeStyle.removeProperty(s);
352
373
  }
353
374
  function setStyleProperty(node, name, value) {
354
375
  value != null ? node.style.setProperty(name, value) : node.style.removeProperty(name);
@@ -387,19 +408,28 @@ function ref(fn, element) {
387
408
  const resolved = solidJs.untrack(fn);
388
409
  solidJs.runWithOwner(null, () => applyRef(resolved, element));
389
410
  }
411
+ function scope(fn) {
412
+ fn.$s = true;
413
+ return fn;
414
+ }
415
+ const SCOPE_OPTIONS = {
416
+ scope: true
417
+ };
418
+ function stripTextSeparators(nodes) {
419
+ let j = 0;
420
+ for (let i = 0; i < nodes.length; i++) {
421
+ if (nodes[i].nodeType === 8 && nodes[i].nodeValue === "!$") nodes[i].remove();else nodes[j++] = nodes[i];
422
+ }
423
+ nodes.length = j;
424
+ return nodes;
425
+ }
390
426
  function insert(parent, accessor, marker, initial, options) {
391
427
  const multi = marker !== undefined;
392
428
  const host = options && options.host;
393
429
  if (multi && !initial) initial = [];
394
430
  if (isHydrating(parent)) {
395
431
  if (!multi && initial === undefined && parent) initial = [...parent.childNodes];
396
- if (Array.isArray(initial)) {
397
- let j = 0;
398
- for (let i = 0; i < initial.length; i++) {
399
- if (initial[i].nodeType === 8 && initial[i].nodeValue === "!$") initial[i].remove();else initial[j++] = initial[i];
400
- }
401
- initial.length = j;
402
- }
432
+ if (Array.isArray(initial)) stripTextSeparators(initial);
403
433
  }
404
434
  if (typeof accessor !== "function") {
405
435
  accessor = normalize(accessor, initial, multi, true);
@@ -415,10 +445,34 @@ function insert(parent, accessor, marker, initial, options) {
415
445
  initial = [placeholder];
416
446
  }
417
447
  let current = initial;
448
+ function reclaimSwappedRegion() {
449
+ if (!solidJs.sharedConfig.hydrating || !current || !parent.isConnected) return;
450
+ const first = Array.isArray(current) ? current[0] : current;
451
+ if (!first || !first.nodeType || first.isConnected) return;
452
+ let nodes;
453
+ if (marker) {
454
+ nodes = [];
455
+ let node = marker.previousSibling,
456
+ depth = 0;
457
+ while (node) {
458
+ if (node.nodeType === 8) {
459
+ const v = node.nodeValue;
460
+ if (v === "/") depth++;else if (v === "$") {
461
+ if (depth === 0) break;
462
+ depth--;
463
+ }
464
+ }
465
+ nodes.unshift(node);
466
+ node = node.previousSibling;
467
+ }
468
+ } else nodes = [...parent.childNodes];
469
+ current = stripTextSeparators(nodes);
470
+ }
418
471
  effect(prev => {
472
+ reclaimSwappedRegion();
419
473
  const value = normalize(accessor(), current, multi, true);
420
474
  if (typeof value !== "function") return value;
421
- effect(() => normalize(value, current, multi), inner => {
475
+ effect(() => (reclaimSwappedRegion(), normalize(value, current, multi)), inner => {
422
476
  insertExpression(parent, inner, current, marker);
423
477
  current = inner;
424
478
  host && tagHost(current, host);
@@ -432,7 +486,11 @@ function insert(parent, accessor, marker, initial, options) {
432
486
  insertExpression(parent, value, current, marker);
433
487
  current = value;
434
488
  host && tagHost(current, host);
435
- }, options);
489
+ },
490
+ accessor.$s ? options ? {
491
+ ...options,
492
+ scope: true
493
+ } : SCOPE_OPTIONS : options);
436
494
  }
437
495
  function assign(node, props, skipChildren, prevProps = {}, skipRef = false) {
438
496
  const nodeName = node.nodeName;
@@ -451,19 +509,117 @@ function assign(node, props, skipChildren, prevProps = {}, skipRef = false) {
451
509
  prevProps[prop] = assignProp(node, prop, props[prop], prevProps[prop], skipRef, nodeName);
452
510
  }
453
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
+ }
454
607
  function loadModuleAssets(mapping) {
455
608
  const hy = globalThis._$HY;
456
609
  if (!hy) return;
457
610
  const pending = [];
458
- for (const moduleUrl in mapping) {
459
- if (hy.modules[moduleUrl]) continue;
460
- const entryUrl = mapping[moduleUrl];
461
- if (!hy.loading[moduleUrl]) {
462
- hy.loading[moduleUrl] = import(entryUrl).then(mod => {
463
- 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;
617
+ }, err => {
618
+ delete hy.loading[key];
619
+ throw err;
464
620
  });
465
621
  }
466
- pending.push(hy.loading[moduleUrl]);
622
+ pending.push(hy.loading[key]);
467
623
  }
468
624
  return pending.length ? Promise.all(pending).then(() => {}) : undefined;
469
625
  }
@@ -518,8 +674,11 @@ function hydrate$1(code, element, options = {}) {
518
674
  } finally {
519
675
  solidJs.sharedConfig.hydrating = false;
520
676
  }
521
- }, () => {
677
+ }, err => {
678
+ console.error("Hydration module preload failed, falling back to client render:", err);
522
679
  solidJs.sharedConfig.hydrating = false;
680
+ solidJs.sharedConfig.registry = undefined;
681
+ disposer = render$1(code, element, [...element.childNodes], options);
523
682
  });
524
683
  return () => disposer && disposer();
525
684
  }
@@ -631,17 +790,32 @@ function runHydrationEvents() {
631
790
  const [el, e] = events[0];
632
791
  if (!completed.has(el)) return;
633
792
  events.shift();
634
- let match;
793
+ let matchContainer, matchState, matchDistance, matches;
635
794
  for (const [container, state] of delegatedContainers) {
636
795
  if (!state.handlers.has(e.type)) continue;
637
796
  const entry = findOwner(e.target, state);
638
- if (entry && (!match || entry.distance < match.distance)) match = {
639
- container,
640
- state,
641
- distance: entry.distance
642
- };
797
+ if (!entry) continue;
798
+ if (matchContainer) {
799
+ if (!matches) matches = [{
800
+ container: matchContainer,
801
+ state: matchState,
802
+ distance: matchDistance
803
+ }];
804
+ matches.push({
805
+ container,
806
+ state,
807
+ distance: entry.distance
808
+ });
809
+ } else {
810
+ matchContainer = container;
811
+ matchState = state;
812
+ matchDistance = entry.distance;
813
+ }
643
814
  }
644
- if (match) eventHandler(e, match.container, match.state);
815
+ if (matches) {
816
+ matches.sort((a, b) => a.distance - b.distance);
817
+ for (let i = 0; i < matches.length; i++) eventHandler(e, matches[i].container, matches[i].state);
818
+ } else if (matchContainer) eventHandler(e, matchContainer, matchState);
645
819
  }
646
820
  if (solidJs.sharedConfig.done) {
647
821
  solidJs.sharedConfig.events = _$HY.events = null;
@@ -712,11 +886,16 @@ function eventHandler(e, container, state) {
712
886
  if (solidJs.sharedConfig.registry && solidJs.sharedConfig.events) {
713
887
  if (solidJs.sharedConfig.events.find(([el, ev]) => ev === e)) return;
714
888
  }
715
- if (e[$$EVENT_OWNER]) return;
889
+ const prev = e[$$EVENT_OWNER];
890
+ let resumeNode;
891
+ if (prev) {
892
+ if (prev === true || prev === container || !container.contains(prev)) return;
893
+ resumeNode = prev;
894
+ }
716
895
  const owner = state && (state.owners.size === 1 && state.owners.has(container) ? container : findOwner(e.target, state)?.owner);
717
896
  if (state && !owner) return;
718
897
  e[$$EVENT_OWNER] = owner || true;
719
- let node = e.target;
898
+ let node = resumeNode || e.target;
720
899
  const key = `$$${e.type}`;
721
900
  const oriTarget = e.target;
722
901
  const boundary = owner || container || e.currentTarget;
@@ -746,7 +925,10 @@ function eventHandler(e, container, state) {
746
925
  return node || boundary || document;
747
926
  }
748
927
  });
749
- if (e.composedPath) {
928
+ if (resumeNode) {
929
+ if (resumeNode === e.target) node = resumeNode._$host || resumeNode.parentNode || resumeNode.host;
930
+ if (node && node !== boundary) walkUpTree();
931
+ } else if (e.composedPath) {
750
932
  const path = e.composedPath();
751
933
  if (path.length) {
752
934
  retarget(path[0]);
@@ -776,7 +958,13 @@ function insertExpression(parent, value, current, marker) {
776
958
  const tc = typeof current;
777
959
  if (tc === "string" || tc === "number") {
778
960
  parent.firstChild.data = value;
779
- } else parent.textContent = value;
961
+ } else {
962
+ const owned = ownedChildCount(current);
963
+ if (owned === -1 || owned === parent.childNodes.length) parent.textContent = value;else {
964
+ removeOwnedChildren(parent, current);
965
+ parent.insertBefore(document.createTextNode(value), parent.firstChild);
966
+ }
967
+ }
780
968
  } else if (value === undefined) {
781
969
  cleanChildren(parent, current, marker);
782
970
  } else if (value.nodeType) {
@@ -799,7 +987,7 @@ function insertExpression(parent, value, current, marker) {
799
987
  appendNodes(parent, value, marker);
800
988
  } else reconcileArrays(parent, current, value, marker);
801
989
  } else {
802
- current && cleanChildren(parent);
990
+ current && cleanChildren(parent, current);
803
991
  appendNodes(parent, value);
804
992
  }
805
993
  } else console.warn(`Unrecognized value. Skipped inserting`, value);
@@ -839,8 +1027,31 @@ function appendNodes(parent, array, marker = null) {
839
1027
  if (marker) n[$$SLOT] = marker;
840
1028
  }
841
1029
  }
1030
+ function ownedChildCount(current) {
1031
+ if (Array.isArray(current)) return current.length;
1032
+ if (current == null) return -1;
1033
+ if (current === "") return 0;
1034
+ return 1;
1035
+ }
1036
+ function removeOwnedChildren(parent, current) {
1037
+ if (Array.isArray(current)) {
1038
+ for (let i = 0; i < current.length; i++) {
1039
+ const el = current[i];
1040
+ if (el.parentNode === parent) el.remove();
1041
+ }
1042
+ } else if (current.nodeType) {
1043
+ if (current.parentNode === parent) current.remove();
1044
+ } else {
1045
+ const first = parent.firstChild;
1046
+ if (first && first.nodeType === 3) first.remove();
1047
+ }
1048
+ }
842
1049
  function cleanChildren(parent, current, marker, replacement) {
843
- if (marker === undefined) return parent.textContent = "";
1050
+ if (marker === undefined) {
1051
+ const owned = ownedChildCount(current);
1052
+ if (owned === -1 || owned === parent.childNodes.length) return parent.textContent = "";
1053
+ return removeOwnedChildren(parent, current);
1054
+ }
844
1055
  if (current.length) {
845
1056
  let inserted = false;
846
1057
  for (let i = current.length - 1; i >= 0; i--) {
@@ -931,9 +1142,10 @@ function Portal(props) {
931
1142
  return () => {
932
1143
  dispose();
933
1144
  let c = startMarker;
934
- while (c && c !== endMarker) {
1145
+ while (c) {
935
1146
  const n = c.nextSibling;
936
1147
  m.removeChild(c);
1148
+ if (c === endMarker) break;
937
1149
  c = n;
938
1150
  }
939
1151
  };
@@ -1046,6 +1258,7 @@ exports.RawTextElements = RawTextElements;
1046
1258
  exports.RequestContext = RequestContext;
1047
1259
  exports.SVGElements = SVGElements;
1048
1260
  exports.VoidElements = VoidElements;
1261
+ exports.acquireAsset = acquireAsset;
1049
1262
  exports.addEvent = addEvent;
1050
1263
  exports.applyRef = applyRef;
1051
1264
  exports.assign = assign;
@@ -1080,6 +1293,7 @@ exports.renderToString = renderToString;
1080
1293
  exports.renderToStringAsync = renderToStringAsync;
1081
1294
  exports.resolveSSRNode = resolveSSRNode;
1082
1295
  exports.runHydrationEvents = runHydrationEvents;
1296
+ exports.scope = scope;
1083
1297
  exports.setAttribute = setAttribute;
1084
1298
  exports.setAttributeNS = setAttributeNS;
1085
1299
  exports.setProperty = setProperty;