{"ScriptPreparationCode":"// language=HTML\r\nconst html = \u0060\r\n\u003Cbody\u003E\r\n \u003Ch1\u003EDoc with mix of light and shadow DOM custom elements\u003C/h1\u003E\r\n \u003Cp\u003ENOTE: we rely on Chrome\u0027s support for \u0022declarative shadow DOM\u0022\u003C/p\u003E\r\n \u003Cx-light id=\u00221\u0022\u003E\r\n \u003C!-- comment --\u003E\r\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Rerum deserunt\r\n dolor nesciunt ab placeat nostrum. Laborum rem quisquam ullam, officiis\r\n maiores fugiat fuga animi quos. Ex earum a alias magni.\r\n \u003C/x-light\u003E\r\n \u003Cx-shadow id=\u00222\u0022\u003E\r\n \u003Ctemplate shadowroot=\u0022open\u0022\u003E\r\n \u003C!-- comment --\u003E\r\n \u003Cp\u003E\r\n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam amet\r\n error delectus...\r\n \u003C/p\u003E\r\n \u003Cslot\u003E\u003C/slot\u003E\r\n \u003C/template\u003E\r\n \u003C!-- comment --\u003E\r\n Impedit nesciunt excepturi perferendis quis in debitis vitae soluta\r\n voluptatibus praesentium repellat labore quas. Cum unde consectetur\r\n maiores.\r\n \u003C/x-shadow\u003E\r\n \u003Cx-light id=\u00223\u0022\u003E\r\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Rerum deserunt\r\n dolor nesciunt ab placeat nostrum. Laborum rem quisquam ullam, officiis\r\n maiores fugiat fuga animi quos. Ex earum a alias magni.\r\n \u003Cx-light id=\u00223.1\u0022\u003E\r\n \u003Cspan\u003ELorem ipsum dolor sit amet\u003C/span\u003E consectetur adipisicing elit.\r\n Rerum deserunt dolor nesciunt ab placeat nostrum. Laborum rem quisquam\r\n ullam, officiis maiores fugiat fuga animi quos. Ex earum a alias magni.\r\n \u003Cx-light id=\u00223.1.1\u0022\u003E\r\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Rerum\r\n deserunt dolor nesciunt ab placeat nostrum. Laborum rem quisquam\r\n ullam, officiis maiores fugiat fuga animi quos. Ex earum a alias\r\n magni.\r\n \u003C/x-light\u003E\r\n \u003C/x-light\u003E\r\n \u003C/x-light\u003E\r\n \u003Cx-shadow id=\u00224\u0022\u003E\r\n \u003Ctemplate shadowroot=\u0022open\u0022\u003E\r\n \u003Cx-shadow id=\u00224.1\u0022\u003E\r\n \u003Ctemplate shadowroot=\u0022open\u0022\u003E\r\n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam amet\r\n error delectus...\r\n \u003Cslot\u003E\u003C/slot\u003E\r\n \u003Cx-shadow id=\u00224.1.1\u0022\u003E\r\n \u003Ctemplate shadowroot=\u0022open\u0022\u003E\r\n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam\r\n amet error delectus...\r\n \u003Cslot\u003E\u003C/slot\u003E\r\n \u003C/template\u003E\r\n Impedit nesciunt excepturi perferendis quis in debitis vitae\r\n soluta voluptatibus praesentium repellat labore quas. Cum unde\r\n consectetur maiores.\r\n \u003Cx-light id=\u00224.1.1.1\u0022\u003E\r\n \u003Cp\u003E\r\n Lorem ipsum dolor sit amet consectetur adipisicing elit. Rerum\r\n deserunt dolor nesciunt ab placeat nostrum. Laborum rem\r\n quisquam ullam, officiis maiores fugiat fuga animi quos. Ex\r\n earum a alias magni.\r\n \u003C/p\u003E\r\n \u003C/x-light\u003E\r\n \u003C/x-shadow\u003E\r\n \u003C/template\u003E\r\n Impedit nesciunt excepturi perferendis quis in debitis vitae soluta\r\n voluptatibus praesentium repellat labore quas. Cum unde consectetur\r\n maiores.\r\n \u003C/x-shadow\u003E\r\n \u003Cslot\u003E\u003C/slot\u003E\r\n \u003C/template\u003E\r\n \u003Cx-shadow id=\u00225\u0022\u003E\r\n \u003Ctemplate shadowroot=\u0022open\u0022\u003E\r\n Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ullam amet\r\n error delectus...\r\n \u003Cslot\u003E\u003C/slot\u003E\r\n \u003C/template\u003E\r\n Impedit nesciunt excepturi perferendis quis in debitis vitae soluta\r\n voluptatibus praesentium repellat labore quas. Cum unde consectetur\r\n maiores.\r\n \u003C/x-shadow\u003E\r\n \u003C/x-shadow\u003E\r\n\u003C/body\u003E\r\n\u0060;\r\nconst fragment = new DOMParser().parseFromString(html, \u0027text/html\u0027, {\r\n\tincludeShadowRoots: true\r\n});\r\ndocument.body.replaceChildren(fragment.body);\r\n\r\nfunction getAllComponents(walkerFunc, root = document.body, shadowParent) {\r\n const components = []\r\n const lightParentStack = []\r\n let element, customElementType, customElementName, customElement\r\n const walker = walkerFunc(root)\r\n\r\n while ((element = walker.nextNode())) {\r\n if (\r\n (hasShadowRoot = !!element.shadowRoot) ||\r\n (customElementType = getCustomElementType(element))\r\n ) {\r\n while (\r\n lightParentStack.length \u0026\u0026\r\n !isAncestor(element, lightParentStack[0].element)\r\n ) {\r\n lightParentStack.shift()\r\n }\r\n\r\n lightParent = lightParentStack[0]\r\n\r\n if (customElementType) {\r\n customElementName =\r\n customElementType === \u0027built-in\u0027\r\n ? element.getAttribute(\u0027is\u0027)\r\n : element.tagName.toLowerCase()\r\n\r\n customElement = {\r\n type: customElementType,\r\n name: customElementName,\r\n definition: customElements.get(customElementName),\r\n }\r\n } else {\r\n customElement = false\r\n }\r\n\r\n const component = {\r\n element,\r\n hasShadowRoot,\r\n customElement,\r\n shadowParent,\r\n lightParent,\r\n shadowChildren: [],\r\n lightChildren: [],\r\n }\r\n\r\n if (shadowParent) {\r\n shadowParent.shadowChildren.push(component)\r\n }\r\n\r\n if (lightParent) {\r\n lightParent.lightChildren.push(component)\r\n }\r\n\r\n components.push(component)\r\n\r\n // regardless of hasShadowRoot, an element can have light DOM children\r\n lightParentStack.unshift(component)\r\n\r\n if (component.hasShadowRoot) {\r\n components.push(\r\n ...getAllComponents(walkerFunc, element.shadowRoot, component)\r\n )\r\n }\r\n }\r\n }\r\n\r\n return components\r\n}\r\n\r\nfunction getCustomElementType(el) {\r\n return el.tagName.includes(\u0027-\u0027)\r\n ? \u0027autonomous\u0027\r\n : el.hasAttribute(\u0027is\u0027)\r\n ? \u0027built-in\u0027\r\n : null\r\n}\r\n\r\nfunction isAncestor(child, ancestor) {\r\n let parent = child.parentNode\r\n\r\n while (parent) {\r\n if (parent === ancestor) {\r\n return true\r\n }\r\n\r\n parent = parent.parentNode\r\n }\r\n\r\n return false\r\n}\r\n\r\nfunction createComponentIterator(root) {\r\n return document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT, null)\r\n}\r\n\r\nfunction createComponentTreeWalker(root) {\r\n return document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null)\r\n}\r\n","TestCases":[{"Name":"NodeIterator","Code":"console.log(getAllComponents(createComponentIterator))","IsDeferred":false},{"Name":"TreeWalker","Code":"console.log(getAllComponents(createComponentTreeWalker))","IsDeferred":false}]}