@stencil/core 5.0.0-beta.30 → 5.0.0-beta.32

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.
@@ -33,7 +33,7 @@ import "@rollup/pluginutils";
33
33
  import { createHash } from "crypto";
34
34
  import { afterAll, vi } from "vitest";
35
35
  //#region src/version.ts
36
- const version = "5.0.0-beta.30";
36
+ const version = "5.0.0-beta.32";
37
37
  const MEMBER_FLAGS = {
38
38
  String: 1,
39
39
  Number: 2,
@@ -1472,6 +1472,7 @@ const patchSlotAppendChild = (HostElementPrototype) => {
1472
1472
  const { slotName, slotNode } = findSlotFromSlottedNode(newChild, this);
1473
1473
  if (slotNode) {
1474
1474
  addSlotRelocateNode(newChild, slotNode);
1475
+ patchSlottedNode(newChild);
1475
1476
  const slotChildNodes = getSlotChildSiblings(slotNode, slotName);
1476
1477
  const appendAfter = slotChildNodes[slotChildNodes.length - 1];
1477
1478
  const insertedNode = internalCall(internalCall(appendAfter, "parentNode"), "insertBefore")(newChild, appendAfter.nextSibling);
@@ -1494,8 +1495,10 @@ const patchSlotRemoveChild = (ElementPrototype) => {
1494
1495
  ElementPrototype.__removeChild = ElementPrototype.removeChild;
1495
1496
  ElementPrototype.removeChild = function(toRemove) {
1496
1497
  if (toRemove && typeof toRemove["s-sn"] !== "undefined") {
1497
- if (getHostSlotNodes(this.__childNodes || this.childNodes, this.tagName, toRemove["s-sn"]) && toRemove.isConnected) {
1498
- toRemove.remove();
1498
+ const slotNode = getHostSlotNodes(this.__childNodes || this.childNodes, this.tagName, toRemove["s-sn"]);
1499
+ if (slotNode && toRemove.isConnected) {
1500
+ removeSlottedNode(toRemove);
1501
+ if (slotNode[0]) dispatchSlotChangeEvent(slotNode[0]);
1499
1502
  updateFallbackSlotVisibility(this);
1500
1503
  return;
1501
1504
  }
@@ -1518,6 +1521,7 @@ const patchSlotPrepend = (HostElementPrototype) => {
1518
1521
  const slotNode = getHostSlotNodes(internalCall(this, "childNodes"), this.tagName, slotName)[0];
1519
1522
  if (slotNode) {
1520
1523
  addSlotRelocateNode(newChild, slotNode, true);
1524
+ patchSlottedNode(newChild);
1521
1525
  const appendAfter = getSlotChildSiblings(slotNode, slotName)[0];
1522
1526
  const toReturn = internalCall(internalCall(appendAfter, "parentNode"), "insertBefore")(newChild, internalCall(appendAfter, "nextSibling"));
1523
1527
  dispatchSlotChangeEvent(slotNode);
@@ -1593,6 +1597,7 @@ const patchInsertBefore = (HostElementPrototype) => {
1593
1597
  }
1594
1598
  if (slotName === currentChild["s-sn"]) {
1595
1599
  addSlotRelocateNode(newChild, slotNode);
1600
+ patchSlottedNode(newChild);
1596
1601
  internalCall(internalCall(currentChild, "parentNode"), "insertBefore")(newChild, currentChild);
1597
1602
  dispatchSlotChangeEvent(slotNode);
1598
1603
  }
@@ -1671,10 +1676,21 @@ const patchChildSlotNodes = (elm) => {
1671
1676
  } });
1672
1677
  };
1673
1678
  /**
1674
- * Patches sibling accessors of a 'slotted' node within a non-shadow component.
1675
- * Meaning whilst stepping through a non-shadow element's nodes, only the mock 'lightDOM' nodes are returned.
1676
- * Especially relevant when rendering components via SSR... Frameworks will often try to reconcile their
1677
- * VDOM with the real DOM by stepping through nodes with 'nextSibling' et al.
1679
+ * Patches a node slotted into a non-shadow component so it behaves as it would in a native slot:
1680
+ * - `parentNode` returns the host element
1681
+ * - `remove()` fires `slotchange` on the node's slot
1682
+ *
1683
+ * @param node the slotted node to be patched
1684
+ */
1685
+ const patchSlottedNode = (node) => {
1686
+ patchParentNode(node);
1687
+ patchSlottedRemove(node);
1688
+ };
1689
+ /**
1690
+ * Patches a slotted node from SSR markup: everything {@link patchSlottedNode} does, plus its
1691
+ * sibling accessors, so whilst stepping through a non-shadow element's nodes only the mock
1692
+ * 'lightDOM' nodes are returned. Frameworks hydrating SSR output often reconcile their VDOM with
1693
+ * the real DOM by stepping through nodes with 'nextSibling' et al.
1678
1694
  * - `nextSibling`
1679
1695
  * - `nextElementSibling`
1680
1696
  * - `previousSibling`
@@ -1682,11 +1698,11 @@ const patchChildSlotNodes = (elm) => {
1682
1698
  *
1683
1699
  * @param node the slotted node to be patched
1684
1700
  */
1685
- const patchSlottedNode = (node) => {
1701
+ const patchSsrSlottedNode = (node) => {
1686
1702
  if (!node || node.__nextSibling !== void 0 || !globalThis.Node) return;
1687
1703
  patchNextSibling(node);
1688
1704
  patchPreviousSibling(node);
1689
- patchParentNode(node);
1705
+ patchSlottedNode(node);
1690
1706
  if (node.nodeType === Node.ELEMENT_NODE) {
1691
1707
  patchNextElementSibling(node);
1692
1708
  patchPreviousElementSibling(node);
@@ -1753,6 +1769,39 @@ const patchPreviousElementSibling = (element) => {
1753
1769
  } });
1754
1770
  };
1755
1771
  /**
1772
+ * Detaches a slotted node from where it physically sits in the component's rendered DOM, through
1773
+ * the unpatched accessors. Not via `remove()`: mock-doc's `remove()` calls
1774
+ * `parentNode.removeChild()`, and a slotted node's patched `parentNode` is the host, whose patched
1775
+ * `removeChild()` would come straight back here.
1776
+ *
1777
+ * @param node the slotted node to detach
1778
+ */
1779
+ const removeSlottedNode = (node) => {
1780
+ const parent = internalCall(node, "parentNode");
1781
+ if (parent) internalCall(parent, "removeChild")(node);
1782
+ };
1783
+ /**
1784
+ * Patches `remove()` on a node slotted into a non-shadow component, so that removing it fires
1785
+ * `slotchange` on its slot (and updates fallback content), as removing a node from a native slot
1786
+ * does. Stencil's own node moves, while `isTmpDisconnected` is set, don't fire it.
1787
+ *
1788
+ * @param node the slotted node to patch
1789
+ */
1790
+ const patchSlottedRemove = (node) => {
1791
+ const child = node;
1792
+ if (!child || child.__remove || typeof child.remove !== "function") return;
1793
+ child.__remove = child.remove;
1794
+ child.remove = function() {
1795
+ const host = this["s-ol"]?.parentElement;
1796
+ const { slotNode } = findSlotFromSlottedNode(this);
1797
+ removeSlottedNode(this);
1798
+ if (slotNode && !(plt.$flags$ & PLATFORM_FLAGS.isTmpDisconnected)) {
1799
+ dispatchSlotChangeEvent(slotNode);
1800
+ updateFallbackSlotVisibility(host);
1801
+ }
1802
+ };
1803
+ };
1804
+ /**
1756
1805
  * Patches the `parentNode` accessor of a non-shadow slotted node
1757
1806
  *
1758
1807
  * @param node the slotted node to be patched
@@ -2382,6 +2431,7 @@ let isSvgMode = false;
2382
2431
  * These ensure that ref callbacks are called in the correct order:
2383
2432
  * first all removal callbacks (with null), then all attachment callbacks (with elements).
2384
2433
  */
2434
+ const initialSlotChanges = /* @__PURE__ */ new Set();
2385
2435
  const refCallbacksToRemove = [];
2386
2436
  const refCallbacksToAttach = [];
2387
2437
  /** Disposers for signal subscriptions on individual DOM nodes (text nodes, <s-show> wrappers). */
@@ -2936,10 +2986,13 @@ const insertBefore = (parent, newNode, reference, isInitialLoad) => {
2936
2986
  if (BUILD.scoped && typeof newNode["s-sn"] === "string" && !!newNode["s-sr"] && !!newNode["s-cr"]) addRemoveSlotScopedClass(newNode["s-cr"], newNode, parent, newNode.parentElement);
2937
2987
  else if (typeof newNode["s-sn"] === "string") {
2938
2988
  const hostElm = newNode["s-hn"] && parent.closest?.(newNode["s-hn"]);
2939
- if ((BUILD.lightDomPatches || BUILD.slotChildNodes || BUILD.patchAll && !!(hostElm && getHostRef(hostElm)?.$cmpMeta$.$flags$ & CMP_FLAGS.patchAll)) && parent.getRootNode().nodeType !== NODE_TYPES.DOCUMENT_FRAGMENT_NODE) patchParentNode(newNode);
2989
+ if ((BUILD.lightDomPatches || BUILD.slotChildNodes || BUILD.patchAll && !!(hostElm && getHostRef(hostElm)?.$cmpMeta$.$flags$ & CMP_FLAGS.patchAll)) && parent.getRootNode().nodeType !== NODE_TYPES.DOCUMENT_FRAGMENT_NODE) patchSlottedNode(newNode);
2940
2990
  parent.insertBefore(newNode, reference);
2941
2991
  const { slotNode } = findSlotFromSlottedNode(newNode);
2942
- if (slotNode && !isInitialLoad) dispatchSlotChangeEvent(slotNode);
2992
+ if (slotNode) {
2993
+ if (isInitialLoad) initialSlotChanges.add(slotNode);
2994
+ else dispatchSlotChangeEvent(slotNode);
2995
+ }
2943
2996
  return newNode;
2944
2997
  }
2945
2998
  }
@@ -3095,6 +3148,11 @@ render() {
3095
3148
  if (checkSlotFallbackVisibility) updateFallbackSlotVisibility(rootVnode.$elm$);
3096
3149
  plt.$flags$ &= ~PLATFORM_FLAGS.isTmpDisconnected;
3097
3150
  relocateNodes.length = 0;
3151
+ if (initialSlotChanges.size) {
3152
+ const slotNodes = [...initialSlotChanges];
3153
+ initialSlotChanges.clear();
3154
+ nextTick(() => slotNodes.forEach(dispatchSlotChangeEvent));
3155
+ }
3098
3156
  }
3099
3157
  if (BUILD.slotRelocation && !useNativeShadowDom && !(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) && hostElm["s-cr"]) {
3100
3158
  const children = rootVnode.$elm$.__childNodes || rootVnode.$elm$.childNodes;
@@ -3847,7 +3905,7 @@ const initializeClientHydrate = (hostElm, tagName, hostId, hostRef) => {
3847
3905
  }
3848
3906
  addSlotRelocateNode(siNode, siSlot, false, siNode["s-oo"] || currentPos);
3849
3907
  if (siNode.parentElement?.shadowRoot && siNode["getAttribute"] && siNode.getAttribute("slot")) siNode.removeAttribute("slot");
3850
- if (BUILD.lightDomPatches || BUILD.slotChildNodes || BUILD.patchAll && hostRef.$cmpMeta$.$flags$ & CMP_FLAGS.patchAll) patchSlottedNode(siNode);
3908
+ if (BUILD.lightDomPatches || BUILD.slotChildNodes || BUILD.patchAll && hostRef.$cmpMeta$.$flags$ & CMP_FLAGS.patchAll) patchSsrSlottedNode(siNode);
3851
3909
  }
3852
3910
  currentPos = (siNode["s-oo"] || currentPos) + 1;
3853
3911
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stencil/core",
3
- "version": "5.0.0-beta.30",
3
+ "version": "5.0.0-beta.32",
4
4
  "description": "A Compiler for Web Components and Progressive Web Apps",
5
5
  "keywords": [
6
6
  "components",
@@ -126,9 +126,9 @@
126
126
  "terser": "^5.50.0",
127
127
  "tinyglobby": "^0.2.17",
128
128
  "typescript": ">5.0.0 <7.0.0",
129
- "@stencil/cli": "5.0.0-beta.30",
130
- "@stencil/mock-doc": "5.0.0-beta.30",
131
- "@stencil/dev-server": "5.0.0-beta.30"
129
+ "@stencil/cli": "5.0.0-beta.32",
130
+ "@stencil/dev-server": "5.0.0-beta.32",
131
+ "@stencil/mock-doc": "5.0.0-beta.32"
132
132
  },
133
133
  "devDependencies": {
134
134
  "@ionic/prettier-config": "^4.0.0",