Summary
Parsing fails when a compound selector contains an attribute selector with the case-insensitive i flag and a pseudo-class, followed by a combinator and another quoted attribute selector. The quotes of the second attribute selector appear to get corrupted during selector normalization (they show up as commas in the error message).
Reproduced on nwsapi 2.2.23 (via jsdom 22.1.0) and 2.2.27 (latest).
Minimal reproduction
const { JSDOM } = require('jsdom');
const dom = new JSDOM('<div><p class="a">t</p><p class="b" id="t"></p></div>');
const el = dom.window.document.getElementById('t');
el.matches("[class*='a' i]:not(:empty) + [class*='b']");
// SyntaxError: '[class*='a' i]:not(:empty)+[class*,,,b,,' is not a valid selector
Note the mangled quotes (,,,b,,) in the error message.
Variants tested
| Selector |
Result |
[class*='a' i]:not(:empty) + [class*='b'] |
❌ FAIL |
[class*="a" i]:not(:empty) + [class*="b"] |
❌ FAIL (double quotes too) |
[class*='a' i]:not(.x) + [class*='b'] |
❌ FAIL (any pseudo-class) |
[class*='a' i]:empty + [class*='b'] |
❌ FAIL |
[class*='a' i]:not(:empty) |
✅ OK (no trailing attribute selector) |
[class*='a' i]:not(:empty) + b |
✅ OK (unquoted second selector) |
[class*='a' i] + [class*='b' i] |
✅ OK (no pseudo-class) |
[class*='a']:not(:empty) + [class*='b'] |
✅ OK (no i flag) |
So all three ingredients are required to trigger it: the i flag, a pseudo-class on the same compound, and a following quoted attribute selector.
All failing selectors are valid per CSS Selectors Level 4 and match correctly in browsers.
Environment
- nwsapi 2.2.23 and 2.2.27
- Node.js 24.5.0
- Encountered in the wild via jsdom → @testing-library/user-event (
pointer-events check calls matches() against all stylesheet rules, so any such selector in a stylesheet breaks unrelated tests)
Possibly related: #159 (quote/escape handling introduced in 2.2.23), #60, #89 — but this repro fails on 2.2.27 as well.
Summary
Parsing fails when a compound selector contains an attribute selector with the case-insensitive
iflag and a pseudo-class, followed by a combinator and another quoted attribute selector. The quotes of the second attribute selector appear to get corrupted during selector normalization (they show up as commas in the error message).Reproduced on nwsapi 2.2.23 (via jsdom 22.1.0) and 2.2.27 (latest).
Minimal reproduction
Note the mangled quotes (
,,,b,,) in the error message.Variants tested
[class*='a' i]:not(:empty) + [class*='b'][class*="a" i]:not(:empty) + [class*="b"][class*='a' i]:not(.x) + [class*='b'][class*='a' i]:empty + [class*='b'][class*='a' i]:not(:empty)[class*='a' i]:not(:empty) + b[class*='a' i] + [class*='b' i][class*='a']:not(:empty) + [class*='b']iflag)So all three ingredients are required to trigger it: the
iflag, a pseudo-class on the same compound, and a following quoted attribute selector.All failing selectors are valid per CSS Selectors Level 4 and match correctly in browsers.
Environment
pointer-eventscheck callsmatches()against all stylesheet rules, so any such selector in a stylesheet breaks unrelated tests)Possibly related: #159 (quote/escape handling introduced in 2.2.23), #60, #89 — but this repro fails on 2.2.27 as well.