Skip to content

Commit 56f8175

Browse files
committed
fix: prevent invalid child combinators in shadow DOM
refs #1100
1 parent 4047d89 commit 56f8175

3 files changed

Lines changed: 18 additions & 2 deletions

File tree

src/selector-nth-child.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { getIntersection } from "./utilities-data.js";
77
export function getElementNthChildSelector(
88
element: Element,
99
): CssSelectorGenerated[] {
10-
const siblings = element.parentElement?.children;
10+
const parent = element.parentNode;
11+
const siblings = parent && "children" in parent ? parent.children : null;
1112
if (siblings) {
1213
for (let i = 0; i < siblings.length; i++) {
1314
if (siblings[i] === element) {

src/selector-nth-of-type.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ export function getElementNthOfTypeSelector(
99
element: Element,
1010
): CssSelectorGenerated[] {
1111
const tag = getTagSelector([element])[0];
12-
const parentElement = element.parentElement;
12+
const parent = element.parentNode;
13+
const parentElement = parent && "children" in parent ? parent : null;
1314

1415
if (parentElement) {
1516
const siblings = Array.from(parentElement.children).filter(

test/shadow-dom.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { assert } from "chai";
22
import { getCssSelector } from "../src";
33
import { getIdSelector } from "../src/selector-id.js";
4+
import { testSelector } from "../src/utilities-dom";
45

56
describe("Shadow DOM", () => {
67
let root: Element;
@@ -33,4 +34,17 @@ describe("Shadow DOM", () => {
3334
const result = getIdSelector([shadowElement])[0];
3435
assert.equal(result, "#shadowElement");
3536
});
37+
38+
it("should not generate invalid selectors for shadow root children without identifiers", () => {
39+
// force creation of a fallback selector
40+
shadowRoot.replaceChildren();
41+
const testElement = shadowRoot.appendChild(document.createElement("div"));
42+
shadowRoot.appendChild(document.createElement("div"));
43+
44+
const result = getCssSelector(testElement, { root: shadowRoot });
45+
46+
assert.notMatch(result, />\s*>/); // consecutive child combinators
47+
assert.notMatch(result, />\s*$/); // trailing child combinator
48+
assert.ok(testSelector([testElement], result, shadowRoot));
49+
});
3650
});

0 commit comments

Comments
 (0)