Diff
Modified: trunk/LayoutTests/ChangeLog (175445 => 175446)
--- trunk/LayoutTests/ChangeLog 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/LayoutTests/ChangeLog 2014-11-01 03:06:27 UTC (rev 175446)
@@ -1,3 +1,17 @@
+2014-10-31 Dhi Aurrahman <[email protected]>
+
+ Add initial parsing functionality of :lang pseudo class in Selectors Level 4.
+ https://bugs.webkit.org/show_bug.cgi?id=138170
+
+ Reviewed by Benjamin Poulain.
+
+ Add tests for comma-separated list arguments for :lang
+
+ * fast/css/css-selector-text-expected.txt: Updated.
+ * fast/css/css-selector-text.html: Updated.
+ * fast/selectors/lang-invalid-expected.txt: Added.
+ * fast/selectors/lang-invalid.html: Added.
+
2014-10-31 Benjamin Poulain <[email protected]>
Pseudo classes with an escaped parenthesis generate invalid rules
Modified: trunk/LayoutTests/fast/css/css-selector-text-expected.txt (175445 => 175446)
--- trunk/LayoutTests/fast/css/css-selector-text-expected.txt 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/LayoutTests/fast/css/css-selector-text-expected.txt 2014-11-01 03:06:27 UTC (rev 175446)
@@ -48,6 +48,13 @@
PASS parseThenSerializeRule(':visited { }') is ':visited { }'
PASS parseThenSerializeRule(':lang(a) { }') is ':lang(a) { }'
+PASS parseThenSerializeRule(':lang(a, b, c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(fr, de, en, id) { }') is ':lang(fr, de, en, id) { }'
+PASS parseThenSerializeRule(':lang(fr, fr-ca, fr-be) { }') is ':lang(fr, fr-ca, fr-be) { }'
+PASS parseThenSerializeRule(':lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996) { }') is ':lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996) { }'
+PASS parseThenSerializeRule(':lang(de-CH, it-CH, fr-CH, rm-CH) { }') is ':lang(de-CH, it-CH, fr-CH, rm-CH) { }'
+PASS parseThenSerializeRule(':lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996, de-CH, it-CH, fr-CH, rm-CH) { }') is ':lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996, de-CH, it-CH, fr-CH, rm-CH) { }'
+
PASS parseThenSerializeRule(':not(a) { }') is ':not(a) { }'
PASS parseThenSerializeRule(':-webkit-any(a,b,p) { }') is ':-webkit-any(a,b,p) { }'
@@ -245,6 +252,40 @@
PASS parseThenSerializeRule(':not(a.class1.class2.class3:hover ) { }') is ':not(a.class1.class2.class3:hover) { }'
PASS parseThenSerializeRule(':not(:matches(single ),:matches(a,b ,p),:matches(#alice, #bob,#chris)) { }') is ':not(:matches(single), :matches(a, b, p), :matches(#alice, #bob, #chris)) { }'
+PASS parseThenSerializeRule(':lang(a ) { }') is ':lang(a) { }'
+PASS parseThenSerializeRule(':lang( a) { }') is ':lang(a) { }'
+PASS parseThenSerializeRule(':lang(a, b, c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang( a, b ,c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang( a , b , c ) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang( a ,b,c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang( a ,b ,c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang( a ,b ,c ) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(a,b ,c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(a,b, c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(a,b, c ) { }') is ':lang(a, b, c) { }'
+
+PASS parseThenSerializeRule(':lang() { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(12, b, c) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(a, 12, c) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(a, b, 12) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(a, 12, 12) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(12, b, 12) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(12, 12, 12) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(lang()) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(:lang()) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(:lang(id)) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(:lang(en, br)) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(<0_0>) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(99) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(88) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(00) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(}) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang({) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang({}) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(]) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang([) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang([]) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(@media screen {}) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/css/css-selector-text.html (175445 => 175446)
--- trunk/LayoutTests/fast/css/css-selector-text.html 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/LayoutTests/fast/css/css-selector-text.html 2014-11-01 03:06:27 UTC (rev 175446)
@@ -81,6 +81,15 @@
debug('');
testSelectorRoundTrip(":lang(a)");
+testSelectorRoundTrip(":lang(a, b, c)");
+testSelectorRoundTrip(":lang(fr, de, en, id)");
+testSelectorRoundTrip(":lang(fr, fr-ca, fr-be)");
+testSelectorRoundTrip(":lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996)");
+testSelectorRoundTrip(":lang(de-CH, it-CH, fr-CH, rm-CH)");
+testSelectorRoundTrip(":lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996, de-CH, it-CH, fr-CH, rm-CH)");
+
+debug('');
+
testSelectorRoundTrip(":not(a)");
testSelectorRoundTrip(":-webkit-any(a,b,p)");
@@ -316,6 +325,43 @@
debug('');
+shouldBe("parseThenSerializeRule(':lang(a ) { }')", "':lang(a) { }'");
+shouldBe("parseThenSerializeRule(':lang( a) { }')", "':lang(a) { }'");
+shouldBe("parseThenSerializeRule(':lang(a, b, c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang( a, b ,c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang( a , b , c ) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang( a ,b,c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang( a ,b ,c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang( a ,b ,c ) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(a,b ,c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(a,b, c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(a,b, c ) { }')", "':lang(a, b, c) { }'");
+
+debug('');
+
+shouldThrow("parseThenSerializeRule(':lang() { }')");
+shouldThrow("parseThenSerializeRule(':lang(12, b, c) { }')");
+shouldThrow("parseThenSerializeRule(':lang(a, 12, c) { }')");
+shouldThrow("parseThenSerializeRule(':lang(a, b, 12) { }')");
+shouldThrow("parseThenSerializeRule(':lang(a, 12, 12) { }')");
+shouldThrow("parseThenSerializeRule(':lang(12, b, 12) { }')");
+shouldThrow("parseThenSerializeRule(':lang(12, 12, 12) { }')");
+shouldThrow("parseThenSerializeRule(':lang(lang()) { }')");
+shouldThrow("parseThenSerializeRule(':lang(:lang()) { }')");
+shouldThrow("parseThenSerializeRule(':lang(:lang(id)) { }')");
+shouldThrow("parseThenSerializeRule(':lang(:lang(en, br)) { }')");
+shouldThrow("parseThenSerializeRule(':lang(<0_0>) { }')");
+shouldThrow("parseThenSerializeRule(':lang(99) { }')");
+shouldThrow("parseThenSerializeRule(':lang(88) { }')");
+shouldThrow("parseThenSerializeRule(':lang(00) { }')");
+shouldThrow("parseThenSerializeRule(':lang(}) { }')");
+shouldThrow("parseThenSerializeRule(':lang({) { }')");
+shouldThrow("parseThenSerializeRule(':lang({}) { }')");
+shouldThrow("parseThenSerializeRule(':lang(]) { }')");
+shouldThrow("parseThenSerializeRule(':lang([) { }')");
+shouldThrow("parseThenSerializeRule(':lang([]) { }')");
+shouldThrow("parseThenSerializeRule(':lang(@media screen {}) { }')");
+
</script>
<script src=""
</body>
Added: trunk/LayoutTests/fast/selectors/lang-invalid-expected.txt (0 => 175446)
--- trunk/LayoutTests/fast/selectors/lang-invalid-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/selectors/lang-invalid-expected.txt 2014-11-01 03:06:27 UTC (rev 175446)
@@ -0,0 +1,39 @@
+Verify invalid :lang() selectors.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.querySelectorAll(":lang()").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(lang()").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(:lang(id)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(:lang(en, br)").length threw exception Error: SyntaxError: DOM Exception 12.
+
+PASS document.querySelectorAll(":lang(<0_0>)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(9)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(99)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(999)").length threw exception Error: SyntaxError: DOM Exception 12.
+
+PASS document.querySelectorAll(":lang(})").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang({)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang({}")).length threw exception SyntaxError: Unexpected token ')'.
+PASS document.querySelectorAll(":lang(()").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang())").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(()")).length threw exception SyntaxError: Unexpected token ')'.
+PASS document.querySelectorAll(":lang(])").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang([)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang([])").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(@media screen {})").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(@font-face {})").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(:)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(;)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(.)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(+)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(-)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(=)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(&&)").length threw exception Error: SyntaxError: DOM Exception 12.
+
+PASS getComputedStyle(document.getElementById("target1")).color is "rgb(0, 0, 0)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/selectors/lang-invalid.html (0 => 175446)
--- trunk/LayoutTests/fast/selectors/lang-invalid.html (rev 0)
+++ trunk/LayoutTests/fast/selectors/lang-invalid.html 2014-11-01 03:06:27 UTC (rev 175446)
@@ -0,0 +1,68 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+* {
+ color: rgb(0, 0, 0);
+}
+:lang() {
+ color: rgb(1, 2, 3);
+}
+
+:lang() * {
+ color: rgb(4, 5, 6);
+}
+</style>
+</head>
+<body>
+ <div style="display:none">
+ <a>
+ <b>
+ <c id="target1"></c>
+ </b>
+ </a>
+ </div>
+</body>
+<script>
+description('Verify invalid :lang() selectors.');
+
+shouldThrow('document.querySelectorAll(":lang()").length');
+shouldThrow('document.querySelectorAll(":lang(lang()").length');
+shouldThrow('document.querySelectorAll(":lang(:lang(id)").length');
+shouldThrow('document.querySelectorAll(":lang(:lang(en, br)").length');
+
+debug('')
+
+shouldThrow('document.querySelectorAll(":lang(<0_0>)").length');
+shouldThrow('document.querySelectorAll(":lang(9)").length');
+shouldThrow('document.querySelectorAll(":lang(99)").length');
+shouldThrow('document.querySelectorAll(":lang(999)").length');
+
+debug('')
+
+shouldThrow('document.querySelectorAll(":lang(})").length');
+shouldThrow('document.querySelectorAll(":lang({)").length');
+shouldThrow('document.querySelectorAll(":lang({}")).length');
+shouldThrow('document.querySelectorAll(":lang(()").length');
+shouldThrow('document.querySelectorAll(":lang())").length');
+shouldThrow('document.querySelectorAll(":lang(()")).length');
+shouldThrow('document.querySelectorAll(":lang(])").length');
+shouldThrow('document.querySelectorAll(":lang([)").length');
+shouldThrow('document.querySelectorAll(":lang([])").length');
+shouldThrow('document.querySelectorAll(":lang(@media screen {})").length');
+shouldThrow('document.querySelectorAll(":lang(@font-face {})").length');
+shouldThrow('document.querySelectorAll(":lang(:)").length');
+shouldThrow('document.querySelectorAll(":lang(;)").length');
+shouldThrow('document.querySelectorAll(":lang(.)").length');
+shouldThrow('document.querySelectorAll(":lang(+)").length');
+shouldThrow('document.querySelectorAll(":lang(-)").length');
+shouldThrow('document.querySelectorAll(":lang(=)").length');
+shouldThrow('document.querySelectorAll(":lang(&&)").length');
+
+debug('')
+
+shouldBeEqualToString('getComputedStyle(document.getElementById("target1")).color', 'rgb(0, 0, 0)');
+</script>
+<script src=""
+</html>
Modified: trunk/Source/WebCore/ChangeLog (175445 => 175446)
--- trunk/Source/WebCore/ChangeLog 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/ChangeLog 2014-11-01 03:06:27 UTC (rev 175446)
@@ -1,3 +1,40 @@
+2014-10-31 Dhi Aurrahman <[email protected]>
+
+ Add initial parsing functionality of :lang pseudo class in Selectors Level 4.
+ https://bugs.webkit.org/show_bug.cgi?id=138170
+
+ Reviewed by Benjamin Poulain.
+
+ Add initial parsing functionality of :lang pseudo class in Selectors Level 4,
+ as specified in [1].
+
+ It parses comma-separated list of string arguments. Currently, it throws error
+ on arguments with "*" (e.g. :lang(zh, *-hant)).
+
+ Add additional test file fast/selectors/lang-invalid.html along side the
+ fast/css/css-selector-text.html.
+
+ [1] http://dev.w3.org/csswg/selectors4/#the-lang-pseudo
+
+ Test: fast/selectors/lang-invalid.html
+
+ * css/CSSGrammar.y.in:
+ * css/CSSParser.cpp:
+ (WebCore::CSSParser::detectFunctionTypeToken):
+ * css/CSSParserValues.cpp:
+ (WebCore::CSSParserSelector::setArgumentList):
+ * css/CSSParserValues.h:
+ * css/CSSSelector.cpp:
+ (WebCore::appendArgumentList):
+ (WebCore::CSSSelector::selectorText):
+ (WebCore::CSSSelector::setArgumentList):
+ * css/CSSSelector.h:
+ (WebCore::CSSSelector::argumentList):
+ * css/SelectorChecker.cpp:
+ (WebCore::SelectorChecker::checkOne):
+ * cssjit/SelectorCompiler.cpp:
+ (WebCore::SelectorCompiler::addPseudoClassType):
+
2014-10-31 Chris Dumez <[email protected]>
StyleBuilder: Stop using custom code for -webkit-hyphenate-limit-lines
Modified: trunk/Source/WebCore/css/CSSGrammar.y.in (175445 => 175446)
--- trunk/Source/WebCore/css/CSSGrammar.y.in 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSGrammar.y.in 2014-11-01 03:06:27 UTC (rev 175446)
@@ -62,6 +62,7 @@
case NTHCHILDFUNCTION:
case NTHCHILDSELECTORSEPARATOR:
#if ENABLE_CSS_SELECTORS_LEVEL4
+ case LANGFUNCTION:
case MATCHESFUNCTION:
#endif
case UNICODERANGE:
@@ -229,6 +230,7 @@
%token <string> NTHCHILDFUNCTION
#if ENABLE_CSS_SELECTORS_LEVEL4
+%token <string> LANGFUNCTION
%token <string> MATCHESFUNCTION
#endif
@@ -328,6 +330,12 @@
%type <valueList> calc_func_expr calc_func_expr_list calc_func_paren_expr expr key_list maybe_media_value valid_calc_func_expr valid_expr
%destructor { delete $$; } calc_func_expr calc_func_expr_list calc_func_paren_expr expr key_list maybe_media_value valid_calc_func_expr valid_expr
+#if ENABLE_CSS_SELECTORS_LEVEL4
+%union { Vector<CSSParserString>* stringList; }
+%type <stringList> comma_separated_identifiers
+%destructor { delete $$; } comma_separated_identifiers
+#endif
+
%type <string> min_or_max
%type <string> element_name
@@ -1089,6 +1097,24 @@
}
;
+#if ENABLE_CSS_SELECTORS_LEVEL4
+comma_separated_identifiers:
+ IDENT %prec UNIMPORTANT_TOK {
+ $$ = new Vector<CSSParserString>;
+ $$->append($1);
+ }
+ | comma_separated_identifiers maybe_space ',' maybe_space IDENT %prec UNIMPORTANT_TOK {
+ $$ = $1;
+ if ($$)
+ $1->append($5);
+ }
+ | comma_separated_identifiers error {
+ $$ = nullptr;
+ delete $1;
+ }
+ ;
+#endif
+
complex_selector_with_trailing_whitespace:
complex_selector WHITESPACE;
@@ -1337,6 +1363,18 @@
}
#if ENABLE_CSS_SELECTORS_LEVEL4
+ | ':' LANGFUNCTION maybe_space comma_separated_identifiers maybe_space ')' {
+ $$ = nullptr;
+ if ($4) {
+ auto selector = std::make_unique<CSSParserSelector>();
+ selector->setMatch(CSSSelector::PseudoClass);
+ selector->setArgumentList(*std::unique_ptr<Vector<CSSParserString>>($4));
+ selector->setPseudoClassValue($2);
+ if (selector->pseudoClassType() == CSSSelector::PseudoClassLang)
+ $$ = selector.release();
+ }
+ }
+
| ':' MATCHESFUNCTION maybe_space nested_selector_list maybe_space ')' {
$$ = nullptr;
if ($4) {
@@ -1837,7 +1875,7 @@
opening_parenthesis:
'(' | FUNCTION | CALCFUNCTION | MINFUNCTION | MAXFUNCTION | ANYFUNCTION | NOTFUNCTION
#if ENABLE_CSS_SELECTORS_LEVEL4
- | MATCHESFUNCTION
+ | LANGFUNCTION | MATCHESFUNCTION
#endif
#if ENABLE_VIDEO_TRACK
| CUEFUNCTION
Modified: trunk/Source/WebCore/css/CSSParser.cpp (175445 => 175446)
--- trunk/Source/WebCore/css/CSSParser.cpp 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSParser.cpp 2014-11-01 03:06:27 UTC (rev 175446)
@@ -10670,6 +10670,12 @@
m_token = CALCFUNCTION;
return true;
}
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ if (isEqualToCSSIdentifier(name, "lang")) {
+ m_token = LANGFUNCTION;
+ return true;
+ }
+#endif
return false;
#if ENABLE(CSS_SELECTORS_LEVEL4)
Modified: trunk/Source/WebCore/css/CSSParserValues.cpp (175445 => 175446)
--- trunk/Source/WebCore/css/CSSParserValues.cpp 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSParserValues.cpp 2014-11-01 03:06:27 UTC (rev 175446)
@@ -261,6 +261,16 @@
m_selector->setSelectorList(WTF::move(selectorList));
}
+void CSSParserSelector::setArgumentList(Vector<CSSParserString>& stringVector)
+{
+ ASSERT_WITH_MESSAGE(!stringVector.isEmpty(), "No CSS Selector takes an empty argument list.");
+ auto argumentList = std::make_unique<Vector<AtomicString>>();
+ argumentList->reserveInitialCapacity(stringVector.size());
+ for (const AtomicString& argument : stringVector)
+ argumentList->append(argument);
+ m_selector->setArgumentList(WTF::move(argumentList));
+}
+
void CSSParserSelector::setPseudoClassValue(const CSSParserString& pseudoClassString)
{
ASSERT(m_selector->match() == CSSSelector::PseudoClass);
Modified: trunk/Source/WebCore/css/CSSParserValues.h (175445 => 175446)
--- trunk/Source/WebCore/css/CSSParserValues.h 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSParserValues.h 2014-11-01 03:06:27 UTC (rev 175446)
@@ -201,6 +201,9 @@
void adoptSelectorVector(Vector<std::unique_ptr<CSSParserSelector>>& selectorVector);
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ void setArgumentList(Vector<CSSParserString>& stringVector);
+#endif
void setPseudoClassValue(const CSSParserString& pseudoClassString);
CSSSelector::PseudoClassType pseudoClassType() const { return m_selector->pseudoClassType(); }
Modified: trunk/Source/WebCore/css/CSSSelector.cpp (175445 => 175446)
--- trunk/Source/WebCore/css/CSSSelector.cpp 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSSelector.cpp 2014-11-01 03:06:27 UTC (rev 175446)
@@ -253,6 +253,18 @@
}
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+static void appendArgumentList(StringBuilder& str, const Vector<AtomicString>& argumentList)
+{
+ const AtomicString& lastArgument = argumentList.last();
+ for (const AtomicString argument : argumentList) {
+ str.append(argument);
+ if (argument != lastArgument)
+ str.appendLiteral(", ");
+ }
+}
+#endif
+
static void appendSelectorList(StringBuilder& str, const CSSSelectorList* selectorList)
{
const CSSSelector* firstSubSelector = selectorList->first();
@@ -395,7 +407,13 @@
break;
case CSSSelector::PseudoClassLang:
str.appendLiteral(":lang(");
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ ASSERT_WITH_MESSAGE(cs->argumentList() && !cs->argumentList().isEmpty(), "An empty :lang() is invalid and should never be generated by the parser.");
+ appendArgumentList(str, *cs->argumentList());
+ str.append(')');
+#else
appendPseudoClassFunctionTail(str, cs);
+#endif
break;
case CSSSelector::PseudoClassLastChild:
str.appendLiteral(":last-child");
@@ -606,6 +624,14 @@
m_data.m_rareData->m_argument = value;
}
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+void CSSSelector::setArgumentList(std::unique_ptr<Vector<AtomicString>> argumentList)
+{
+ createRareData();
+ m_data.m_rareData->m_argumentList = WTF::move(argumentList);
+}
+#endif
+
void CSSSelector::setSelectorList(std::unique_ptr<CSSSelectorList> selectorList)
{
createRareData();
Modified: trunk/Source/WebCore/css/CSSSelector.h (175445 => 175446)
--- trunk/Source/WebCore/css/CSSSelector.h 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSSelector.h 2014-11-01 03:06:27 UTC (rev 175446)
@@ -207,11 +207,17 @@
const QualifiedName& attribute() const;
const AtomicString& attributeCanonicalLocalName() const;
const AtomicString& argument() const { return m_hasRareData ? m_data.m_rareData->m_argument : nullAtom; }
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ const Vector<AtomicString>* argumentList() const { return m_hasRareData ? m_data.m_rareData->m_argumentList.get() : nullptr; }
+#endif
const CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData->m_selectorList.get() : nullptr; }
void setValue(const AtomicString&);
void setAttribute(const QualifiedName&, bool isCaseInsensitive);
void setArgument(const AtomicString&);
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ void setArgumentList(std::unique_ptr<Vector<AtomicString>>);
+#endif
void setSelectorList(std::unique_ptr<CSSSelectorList>);
bool parseNth() const;
@@ -309,7 +315,10 @@
int m_b; // Used for :nth-*
QualifiedName m_attribute; // used for attribute selector
AtomicString m_attributeCanonicalLocalName;
- AtomicString m_argument; // Used for :contains, :lang and :nth-*
+ AtomicString m_argument; // Used for :contains and :nth-*
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ std::unique_ptr<Vector<AtomicString>> m_argumentList;
+#endif
std::unique_ptr<CSSSelectorList> m_selectorList; // Used for :-webkit-any and :not
private:
Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (175445 => 175446)
--- trunk/Source/WebCore/css/SelectorChecker.cpp 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp 2014-11-01 03:06:27 UTC (rev 175446)
@@ -859,7 +859,12 @@
break;
case CSSSelector::PseudoClassLang:
{
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ ASSERT(selector->argumentList() && !selector->argumentList()->isEmpty());
+ const AtomicString& argument = selector->argumentList()->first();
+#else
const AtomicString& argument = selector->argument();
+#endif
if (argument.isNull())
return false;
return matchesLangPseudoClass(element, argument.impl());
Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (175445 => 175446)
--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp 2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp 2014-11-01 03:06:27 UTC (rev 175446)
@@ -727,7 +727,12 @@
case CSSSelector::PseudoClassLang:
{
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ ASSERT(selector.argumentList() && !selector.argumentList()->isEmpty());
+ const AtomicString& argument = selector.argumentList()->first();
+#else
const AtomicString& argument = selector.argument();
+#endif
if (argument.isEmpty())
return FunctionType::CannotMatchAnything;