Skip to content

Commit 60e1cdf

Browse files
committed
::has, ::is, ::where are invalid
1 parent f49a467 commit 60e1cdf

File tree

9 files changed

+129
-28
lines changed

9 files changed

+129
-28
lines changed

src/main/java/org/htmlunit/cssparser/parser/AbstractCSSParser.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public abstract class AbstractCSSParser {
7171
PARSER_MESSAGES_.put("invalidElementName", "Error in element name.");
7272
PARSER_MESSAGES_.put("invalidAttrib", "Error in attribute selector.");
7373
PARSER_MESSAGES_.put("invalidPseudo", "Error in pseudo class or element.");
74+
PARSER_MESSAGES_.put("invalidPseudoColon", "\":{0}\" is not a valid selector.");
7475
PARSER_MESSAGES_.put("duplicatePseudo", "Duplicate pseudo class \":{0}\" or pseudo class \":{0}\" not at end.");
7576
PARSER_MESSAGES_.put("invalidHash", "Error in hash.");
7677
PARSER_MESSAGES_.put("invalidExpr", "Error in expression.");

src/main/java/org/htmlunit/cssparser/parser/condition/HasPseudoClassCondition.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,22 @@
2121
import org.htmlunit.cssparser.parser.selector.SelectorList;
2222

2323
/**
24-
* Not condition.
24+
* :has condition.
2525
*
2626
* @author Ronald Brill
2727
*/
2828
public class HasPseudoClassCondition extends AbstractLocatable implements Condition, Serializable {
2929

3030
private final SelectorList selectors_;
31-
private final boolean doubleColon_;
3231

3332
/**
3433
* Ctor.
3534
* @param selectors the selector list
3635
* @param locator the locator
37-
* @param doubleColon true if was prefixed by double colon
3836
*/
39-
public HasPseudoClassCondition(final SelectorList selectors, final Locator locator, final boolean doubleColon) {
37+
public HasPseudoClassCondition(final SelectorList selectors, final Locator locator) {
4038
selectors_ = selectors;
4139
setLocator(locator);
42-
doubleColon_ = doubleColon;
4340
}
4441

4542
@Override
@@ -72,6 +69,6 @@ public SelectorList getSelectors() {
7269

7370
@Override
7471
public String toString() {
75-
return (doubleColon_ ? "::" : ":") + "has(" + getValue() + ")";
72+
return ":has(" + getValue() + ")";
7673
}
7774
}

src/main/java/org/htmlunit/cssparser/parser/condition/IsPseudoClassCondition.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,22 @@
2121
import org.htmlunit.cssparser.parser.selector.SelectorList;
2222

2323
/**
24-
* Not condition.
24+
* :is condition.
2525
*
2626
* @author Ronald Brill
2727
*/
2828
public class IsPseudoClassCondition extends AbstractLocatable implements Condition, Serializable {
2929

3030
private final SelectorList selectors_;
31-
private final boolean doubleColon_;
3231

3332
/**
3433
* Ctor.
3534
* @param selectors the selector list
3635
* @param locator the locator
37-
* @param doubleColon true if was prefixed by double colon
3836
*/
39-
public IsPseudoClassCondition(final SelectorList selectors, final Locator locator, final boolean doubleColon) {
37+
public IsPseudoClassCondition(final SelectorList selectors, final Locator locator) {
4038
selectors_ = selectors;
4139
setLocator(locator);
42-
doubleColon_ = doubleColon;
4340
}
4441

4542
@Override
@@ -72,6 +69,6 @@ public SelectorList getSelectors() {
7269

7370
@Override
7471
public String toString() {
75-
return (doubleColon_ ? "::" : ":") + "is(" + getValue() + ")";
72+
return ":is(" + getValue() + ")";
7673
}
7774
}

src/main/java/org/htmlunit/cssparser/parser/condition/WherePseudoClassCondition.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,22 @@
2121
import org.htmlunit.cssparser.parser.selector.SelectorList;
2222

2323
/**
24-
* Not condition.
24+
* :where condition.
2525
*
2626
* @author Ronald Brill
2727
*/
2828
public class WherePseudoClassCondition extends AbstractLocatable implements Condition, Serializable {
2929

3030
private final SelectorList selectors_;
31-
private final boolean doubleColon_;
3231

3332
/**
3433
* Ctor.
3534
* @param selectors the selector list
3635
* @param locator the locator
37-
* @param doubleColon true if was prefixed by double colon
3836
*/
39-
public WherePseudoClassCondition(final SelectorList selectors, final Locator locator, final boolean doubleColon) {
37+
public WherePseudoClassCondition(final SelectorList selectors, final Locator locator) {
4038
selectors_ = selectors;
4139
setLocator(locator);
42-
doubleColon_ = doubleColon;
4340
}
4441

4542
@Override
@@ -72,6 +69,6 @@ public SelectorList getSelectors() {
7269

7370
@Override
7471
public String toString() {
75-
return (doubleColon_ ? "::" : ":") + "where(" + getValue() + ")";
72+
return ":where(" + getValue() + ")";
7673
}
7774
}

src/main/java/org/htmlunit/cssparser/parser/selector/RelativeSelector.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ public SimpleSelector getSimpleSelector() {
5959
/** {@inheritDoc} */
6060
@Override
6161
public String toString() {
62+
if (' ' == combinator_.getChar()) {
63+
return selector_.toString();
64+
}
65+
6266
return combinator_.getChar() + " " + selector_.toString();
6367
}
6468
}

src/main/javacc/CSS3Parser.jj

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,7 +1455,8 @@ Object pseudo(boolean pseudoElementFound) :
14551455
<RROUND>
14561456
{
14571457
if (pseudoElementFound) { throw toCSSParseException("duplicatePseudo", new String[] { function + selectorList + ")" }, locator); }
1458-
return new IsPseudoClassCondition(selectorList, locator, doubleColon);
1458+
if (doubleColon) { throw toCSSParseException("invalidPseudoColon", new String[] { ":" + function + selectorList + ")" }, locator); }
1459+
return new IsPseudoClassCondition(selectorList, locator);
14591460
}
14601461
)
14611462
|
@@ -1466,7 +1467,8 @@ Object pseudo(boolean pseudoElementFound) :
14661467
<RROUND>
14671468
{
14681469
if (pseudoElementFound) { throw toCSSParseException("duplicatePseudo", new String[] { function + selectorList + ")" }, locator); }
1469-
return new WherePseudoClassCondition(selectorList, locator, doubleColon);
1470+
if (doubleColon) { throw toCSSParseException("invalidPseudoColon", new String[] { ":" + function + selectorList + ")" }, locator); }
1471+
return new WherePseudoClassCondition(selectorList, locator);
14701472
}
14711473
)
14721474
|
@@ -1477,7 +1479,8 @@ Object pseudo(boolean pseudoElementFound) :
14771479
<RROUND>
14781480
{
14791481
if (pseudoElementFound) { throw toCSSParseException("duplicatePseudo", new String[] { function + relativeSelectorList + ")" }, locator); }
1480-
return new HasPseudoClassCondition(relativeSelectorList, locator, doubleColon);
1482+
if (doubleColon) { throw toCSSParseException("invalidPseudoColon", new String[] { ":" + function + relativeSelectorList + ")" }, locator); }
1483+
return new HasPseudoClassCondition(relativeSelectorList, locator);
14811484
}
14821485
)
14831486
|

src/test/java/org/htmlunit/cssparser/parser/CSS3ParserHasSelectorTest.java

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import static org.junit.jupiter.api.Assertions.assertEquals;
1818

19+
import org.htmlunit.cssparser.ErrorHandler;
1920
import org.htmlunit.cssparser.parser.condition.Condition;
2021
import org.htmlunit.cssparser.parser.condition.Condition.ConditionType;
2122
import org.htmlunit.cssparser.parser.condition.HasPseudoClassCondition;
@@ -235,17 +236,50 @@ public void syntaxErrors() throws Exception {
235236
parseSelectors(":has(#, h2)", 1, 0, 0);
236237
parseSelectors(":has([attr=], h2)", 1, 0, 0);
237238
parseSelectors(":has([=value], h2)", 1, 0, 0);
239+
240+
parseSelectors("::has(h2)", 1, 0, 0);
241+
}
242+
243+
/**
244+
* @throws Exception if any error occurs
245+
*/
246+
@Test
247+
public void syntaxErrorDoubleColon() throws Exception {
248+
String selector = "::has(h2)";
249+
250+
final CSSOMParser parser = new CSSOMParser();
251+
ErrorHandler errorHandler = new ErrorHandler();
252+
parser.setErrorHandler(errorHandler);
253+
254+
parser.parseSelectors(selector);
255+
256+
assertEquals(1, errorHandler.getErrorCount());
257+
assertEquals(0, errorHandler.getFatalErrorCount());
258+
assertEquals(0, errorHandler.getWarningCount());
259+
260+
assertEquals("\"::has(h2)\" is not a valid selector.", errorHandler.getErrorMessage());
261+
262+
selector = "p::has(h4)";
263+
errorHandler = new ErrorHandler();
264+
parser.setErrorHandler(errorHandler);
265+
parser.parseSelectors(selector);
266+
267+
assertEquals(1, errorHandler.getErrorCount());
268+
assertEquals(0, errorHandler.getFatalErrorCount());
269+
assertEquals(0, errorHandler.getWarningCount());
270+
271+
assertEquals("\"::has(h4)\" is not a valid selector.", errorHandler.getErrorMessage());
238272
}
239273

240274
/**
241275
* @throws Exception if any error occurs
242276
*/
243277
@Test
244278
public void pseudoElementsInside() throws Exception {
245-
// todo parseSelectors("div:has(p::before)", 1, 0, 0);
246-
// todo parseSelectors("section:has(::first-line)", 1, 0, 0);
247-
// todo parseSelectors("article:has(span::after)", 1, 0, 0);
248-
// todo parseSelectors("div:has(p:has(::before))", 1, 0, 0);
279+
parseSelectors("div:has(p::before)", 0, 0, 0);
280+
parseSelectors("section:has(::first-line)", 0, 0, 0);
281+
parseSelectors("article:has(span::after)", 0, 0, 0);
282+
parseSelectors("div:has(p:has(::before))", 0, 0, 0);
249283
}
250284

251285
/**

src/test/java/org/htmlunit/cssparser/parser/CSS3ParserIsSelectorTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import static org.junit.jupiter.api.Assertions.assertEquals;
1818

19+
import org.htmlunit.cssparser.ErrorHandler;
1920
import org.htmlunit.cssparser.parser.condition.Condition;
2021
import org.htmlunit.cssparser.parser.condition.Condition.ConditionType;
2122
import org.htmlunit.cssparser.parser.condition.IsPseudoClassCondition;
@@ -201,6 +202,39 @@ public void syntaxErrors() throws Exception {
201202

202203
parseSelectors(":is(h1, h2", 1, 0, 0);
203204
parseSelectors(":is h1, h2)", 1, 0, 0);
205+
206+
parseSelectors("::is(h2)", 1, 0, 0);
207+
}
208+
209+
/**
210+
* @throws Exception if any error occurs
211+
*/
212+
@Test
213+
public void syntaxErrorDoubleColon() throws Exception {
214+
String selector = "::is(h2)";
215+
216+
final CSSOMParser parser = new CSSOMParser();
217+
ErrorHandler errorHandler = new ErrorHandler();
218+
parser.setErrorHandler(errorHandler);
219+
220+
parser.parseSelectors(selector);
221+
222+
assertEquals(1, errorHandler.getErrorCount());
223+
assertEquals(0, errorHandler.getFatalErrorCount());
224+
assertEquals(0, errorHandler.getWarningCount());
225+
226+
assertEquals("\"::is(h2)\" is not a valid selector.", errorHandler.getErrorMessage());
227+
228+
selector = "p::is(h4)";
229+
errorHandler = new ErrorHandler();
230+
parser.setErrorHandler(errorHandler);
231+
parser.parseSelectors(selector);
232+
233+
assertEquals(1, errorHandler.getErrorCount());
234+
assertEquals(0, errorHandler.getFatalErrorCount());
235+
assertEquals(0, errorHandler.getWarningCount());
236+
237+
assertEquals("\"::is(h4)\" is not a valid selector.", errorHandler.getErrorMessage());
204238
}
205239

206240
/**

src/test/java/org/htmlunit/cssparser/parser/CSS3ParserWhereSelectorTest.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import static org.junit.jupiter.api.Assertions.assertEquals;
1818

19+
import org.htmlunit.cssparser.ErrorHandler;
1920
import org.htmlunit.cssparser.parser.condition.Condition;
2021
import org.htmlunit.cssparser.parser.condition.Condition.ConditionType;
2122
import org.htmlunit.cssparser.parser.condition.WherePseudoClassCondition;
@@ -193,12 +194,45 @@ public void emptyAndWhitespace() throws Exception {
193194
public void syntaxErrors() throws Exception {
194195
// parseSelectors(":where(h1 h2)", 1, 0, 0);
195196
// parseSelectors(":is h1, h2", 1, 0, 0);
196-
parseSelectors("is(h1, h2)", 1, 0, 0);
197+
parseSelectors("where(h1, h2)", 1, 0, 0);
197198
parseSelectors(":where((h1, h2))", 1, 0, 0);
198-
parseSelectors(":is[h1, h2]", 1, 0, 0);
199+
parseSelectors(":where[h1, h2]", 1, 0, 0);
199200

200201
parseSelectors(":where(h1, h2", 1, 0, 0);
201-
parseSelectors(":is h1, h2)", 1, 0, 0);
202+
parseSelectors(":where h1, h2)", 1, 0, 0);
203+
204+
parseSelectors("::where(h2)", 1, 0, 0);
205+
}
206+
207+
/**
208+
* @throws Exception if any error occurs
209+
*/
210+
@Test
211+
public void syntaxErrorDoubleColon() throws Exception {
212+
String selector = "::where(h2)";
213+
214+
final CSSOMParser parser = new CSSOMParser();
215+
ErrorHandler errorHandler = new ErrorHandler();
216+
parser.setErrorHandler(errorHandler);
217+
218+
parser.parseSelectors(selector);
219+
220+
assertEquals(1, errorHandler.getErrorCount());
221+
assertEquals(0, errorHandler.getFatalErrorCount());
222+
assertEquals(0, errorHandler.getWarningCount());
223+
224+
assertEquals("\"::where(h2)\" is not a valid selector.", errorHandler.getErrorMessage());
225+
226+
selector = "p::where(h4)";
227+
errorHandler = new ErrorHandler();
228+
parser.setErrorHandler(errorHandler);
229+
parser.parseSelectors(selector);
230+
231+
assertEquals(1, errorHandler.getErrorCount());
232+
assertEquals(0, errorHandler.getFatalErrorCount());
233+
assertEquals(0, errorHandler.getWarningCount());
234+
235+
assertEquals("\"::where(h4)\" is not a valid selector.", errorHandler.getErrorMessage());
202236
}
203237

204238
/**

0 commit comments

Comments
 (0)