LayoutTests:
authordarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 25 Mar 2007 02:48:31 +0000 (02:48 +0000)
committerdarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 25 Mar 2007 02:48:31 +0000 (02:48 +0000)
        Reviewed by Mitz.

        - test for http://bugs.webkit.org/show_bug.cgi?id=13123
          CSS selectors that use :lang, :not, and namespaces do not serialize correctly

        * fast/css/css-selector-text-expected.txt: Added.
        * fast/css/css-selector-text.html: Added.

WebCore:

        Reviewed by Mitz.

        - fix http://bugs.webkit.org/show_bug.cgi?id=13123
          CSS selectors that use :lang, :not, and namespaces do not serialize correctly

        Test: fast/css/css-selector-text.html

        * css/CSSSelector.cpp: (WebCore::CSSSelector::selectorText): Add the namespace
        prefix for tag or attribute names, the sub-selector for :not, and the argument
        for :lang.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@20477 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/css/css-selector-text-expected.txt [new file with mode: 0644]
LayoutTests/fast/css/css-selector-text.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/css/CSSSelector.cpp

index 012f572c130c2bcd6b0af65ba7c7a507fd9a480a..40e1100e0db8d5676b5f027a0865a7fc4fb88c42 100644 (file)
@@ -1,3 +1,13 @@
+2007-03-24  Darin Adler  <darin@apple.com>
+
+        Reviewed by Mitz.
+
+        - test for http://bugs.webkit.org/show_bug.cgi?id=13123
+          CSS selectors that use :lang, :not, and namespaces do not serialize correctly
+
+        * fast/css/css-selector-text-expected.txt: Added.
+        * fast/css/css-selector-text.html: Added.
+
 2007-03-24  Nikolas Zimmermann  <zimmermann@kde.org>
 
         Reviewed by Oliver.
diff --git a/LayoutTests/fast/css/css-selector-text-expected.txt b/LayoutTests/fast/css/css-selector-text-expected.txt
new file mode 100644 (file)
index 0000000..a595f68
--- /dev/null
@@ -0,0 +1,86 @@
+This tests parsing and re-serialization of some CSS selectors.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS parseThenSerializeRule('* { }') is '* { }'
+PASS parseThenSerializeRule('a { }') is 'a { }'
+PASS parseThenSerializeRule('#a { }') is '#a { }'
+PASS parseThenSerializeRule('.a { }') is '.a { }'
+PASS parseThenSerializeRule(':active { }') is ':active { }'
+PASS parseThenSerializeRule('[a] { }') is '[a] { }'
+PASS parseThenSerializeRule('[a="b"] { }') is '[a="b"] { }'
+PASS parseThenSerializeRule('[a~="b"] { }') is '[a~="b"] { }'
+PASS parseThenSerializeRule('[a|="b"] { }') is '[a|="b"] { }'
+PASS parseThenSerializeRule('[a^="b"] { }') is '[a^="b"] { }'
+PASS parseThenSerializeRule('[a$="b"] { }') is '[a$="b"] { }'
+PASS parseThenSerializeRule('[a*="b"] { }') is '[a*="b"] { }'
+
+PASS parseThenSerializeRule('*|a { }') is '*|a { }'
+PASS parseThenSerializeRule('n|a { }') is 'n|a { }'
+PASS parseThenSerializeRule('*|* { }') is '*|* { }'
+PASS parseThenSerializeRule('n|* { }') is 'n|* { }'
+PASS parseThenSerializeRule('[*|a] { }') is '[*|a] { }'
+PASS parseThenSerializeRule('[n|a] { }') is '[n|a] { }'
+
+PASS parseThenSerializeRule('a:active { }') is 'a:active { }'
+PASS parseThenSerializeRule('a b { }') is 'a b { }'
+PASS parseThenSerializeRule('a + b { }') is 'a + b { }'
+PASS parseThenSerializeRule('a ~ b { }') is 'a ~ b { }'
+PASS parseThenSerializeRule('a > b { }') is 'a > b { }'
+
+PASS parseThenSerializeRule(':active { }') is ':active { }'
+PASS parseThenSerializeRule(':checked { }') is ':checked { }'
+PASS parseThenSerializeRule(':disabled { }') is ':disabled { }'
+PASS parseThenSerializeRule(':empty { }') is ':empty { }'
+PASS parseThenSerializeRule(':enabled { }') is ':enabled { }'
+PASS parseThenSerializeRule(':first-child { }') is ':first-child { }'
+PASS parseThenSerializeRule(':first-of-type { }') is ':first-of-type { }'
+PASS parseThenSerializeRule(':focus { }') is ':focus { }'
+PASS parseThenSerializeRule(':hover { }') is ':hover { }'
+PASS parseThenSerializeRule(':indeterminate { }') is ':indeterminate { }'
+PASS parseThenSerializeRule(':link { }') is ':link { }'
+PASS parseThenSerializeRule(':root { }') is ':root { }'
+PASS parseThenSerializeRule(':target { }') is ':target { }'
+PASS parseThenSerializeRule(':visited { }') is ':visited { }'
+
+PASS parseThenSerializeRule(':lang(a) { }') is ':lang(a) { }'
+PASS parseThenSerializeRule(':not(a) { }') is ':not(a) { }'
+
+PASS parseThenSerializeRule('::after { }') is '::after { }'
+PASS parseThenSerializeRule('::before { }') is '::before { }'
+PASS parseThenSerializeRule('::first-letter { }') is '::first-letter { }'
+PASS parseThenSerializeRule('::first-line { }') is '::first-line { }'
+PASS parseThenSerializeRule('::selection { }') is '::selection { }'
+
+PASS parseThenSerializeRule(':-webkit-any-link { }') is ':-webkit-any-link { }'
+PASS parseThenSerializeRule(':-webkit-autofill { }') is ':-webkit-autofill { }'
+PASS parseThenSerializeRule(':-webkit-drag { }') is ':-webkit-drag { }'
+
+PASS parseThenSerializeRule('::-webkit-file-upload-button { }') is '::-webkit-file-upload-button { }'
+PASS parseThenSerializeRule('::-webkit-search-cancel-button { }') is '::-webkit-search-cancel-button { }'
+PASS parseThenSerializeRule('::-webkit-search-decoration { }') is '::-webkit-search-decoration { }'
+PASS parseThenSerializeRule('::-webkit-search-results-button { }') is '::-webkit-search-results-button { }'
+PASS parseThenSerializeRule('::-webkit-search-results-decoration { }') is '::-webkit-search-results-decoration { }'
+PASS parseThenSerializeRule('::-webkit-slider-thumb { }') is '::-webkit-slider-thumb { }'
+
+PASS parseThenSerializeRule('input:not([type="file"]):focus { }') is 'input:not([type="file"]):focus { }'
+
+PASS parseThenSerializeRule('*:active { }') is ':active { }'
+PASS parseThenSerializeRule('|a { }') is 'a { }'
+
+PASS parseThenSerializeRule('input[type=file]:focus { }') is 'input[type="file"]:focus { }'
+
+PASS parseThenSerializeRule('a+b { }') is 'a + b { }'
+PASS parseThenSerializeRule('a~b { }') is 'a ~ b { }'
+PASS parseThenSerializeRule('a>b { }') is 'a > b { }'
+
+PASS parseThenSerializeRule(':after { }') is '::after { }'
+PASS parseThenSerializeRule(':before { }') is '::before { }'
+PASS parseThenSerializeRule(':first-letter { }') is '::first-letter { }'
+PASS parseThenSerializeRule(':first-line { }') is '::first-line { }'
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/css/css-selector-text.html b/LayoutTests/fast/css/css-selector-text.html
new file mode 100644 (file)
index 0000000..f241e47
--- /dev/null
@@ -0,0 +1,133 @@
+<html>
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+
+description("This tests parsing and re-serialization of some CSS selectors.");
+
+function parseThenSerializeRule(rule)
+{
+    var styleElement = document.createElement("style");
+    styleElement.appendChild(document.createTextNode(rule));
+    return styleElement.sheet.cssRules[0].cssText;
+}
+
+function testSelectorRoundTrip(selector)
+{
+    shouldBe("parseThenSerializeRule('" + selector + " { }')", "'" + selector + " { }'");
+}
+
+testSelectorRoundTrip('*');
+testSelectorRoundTrip('a');
+testSelectorRoundTrip('#a');
+testSelectorRoundTrip('.a');
+testSelectorRoundTrip(':active');
+testSelectorRoundTrip('[a]');
+testSelectorRoundTrip('[a="b"]');
+testSelectorRoundTrip('[a~="b"]');
+testSelectorRoundTrip('[a|="b"]');
+testSelectorRoundTrip('[a^="b"]');
+testSelectorRoundTrip('[a$="b"]');
+testSelectorRoundTrip('[a*="b"]');
+
+debug('');
+
+testSelectorRoundTrip('*|a');
+testSelectorRoundTrip('n|a');
+testSelectorRoundTrip('*|*');
+testSelectorRoundTrip('n|*');
+testSelectorRoundTrip('[*|a]');
+testSelectorRoundTrip('[n|a]');
+
+debug('');
+
+testSelectorRoundTrip('a:active');
+testSelectorRoundTrip('a b');
+testSelectorRoundTrip('a + b');
+testSelectorRoundTrip('a ~ b');
+testSelectorRoundTrip('a > b');
+
+debug('');
+
+testSelectorRoundTrip(":active");
+testSelectorRoundTrip(":checked");
+testSelectorRoundTrip(":disabled");
+testSelectorRoundTrip(":empty");
+testSelectorRoundTrip(":enabled");
+testSelectorRoundTrip(":first-child");
+testSelectorRoundTrip(":first-of-type");
+testSelectorRoundTrip(":focus");
+testSelectorRoundTrip(":hover");
+testSelectorRoundTrip(":indeterminate");
+testSelectorRoundTrip(":link");
+testSelectorRoundTrip(":root");
+testSelectorRoundTrip(":target");
+testSelectorRoundTrip(":visited");
+
+debug('');
+
+testSelectorRoundTrip(":lang(a)");
+testSelectorRoundTrip(":not(a)");
+
+debug('');
+
+testSelectorRoundTrip("::after");
+testSelectorRoundTrip("::before");
+testSelectorRoundTrip("::first-letter");
+testSelectorRoundTrip("::first-line");
+testSelectorRoundTrip("::selection");
+
+debug('');
+
+testSelectorRoundTrip(":-webkit-any-link");
+testSelectorRoundTrip(":-webkit-autofill");
+testSelectorRoundTrip(":-webkit-drag");
+
+debug('');
+
+testSelectorRoundTrip("::-webkit-file-upload-button");
+testSelectorRoundTrip("::-webkit-search-cancel-button");
+testSelectorRoundTrip("::-webkit-search-decoration");
+testSelectorRoundTrip("::-webkit-search-results-button");
+testSelectorRoundTrip("::-webkit-search-results-decoration");
+testSelectorRoundTrip("::-webkit-slider-thumb");
+
+debug('');
+
+testSelectorRoundTrip('input:not([type="file"]):focus');
+
+debug('');
+
+shouldBe("parseThenSerializeRule('*:active { }')", "':active { }'");
+shouldBe("parseThenSerializeRule('|a { }')", "'a { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule('input[type=file]:focus { }')", "'input[type=\"file\"]:focus { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule('a+b { }')", "'a + b { }'");
+shouldBe("parseThenSerializeRule('a~b { }')", "'a ~ b { }'");
+shouldBe("parseThenSerializeRule('a>b { }')", "'a > b { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule(':after { }')", "'::after { }'");
+shouldBe("parseThenSerializeRule(':before { }')", "'::before { }'");
+shouldBe("parseThenSerializeRule(':first-letter { }')", "'::first-letter { }'");
+shouldBe("parseThenSerializeRule(':first-line { }')", "'::first-line { }'");
+
+debug('');
+
+successfullyParsed = true;
+
+</script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
index 0e01a63c9ca294a82f6f27ffbc538eb6d880553a..2fc7e43e98247cfbcf888c3f8be185e33f1bbb7c 100644 (file)
@@ -1,3 +1,16 @@
+2007-03-24  Darin Adler  <darin@apple.com>
+
+        Reviewed by Mitz.
+
+        - fix http://bugs.webkit.org/show_bug.cgi?id=13123
+          CSS selectors that use :lang, :not, and namespaces do not serialize correctly
+
+        Test: fast/css/css-selector-text.html
+
+        * css/CSSSelector.cpp: (WebCore::CSSSelector::selectorText): Add the namespace
+        prefix for tag or attribute names, the sub-selector for :not, and the argument
+        for :lang.
+
 2007-03-24  Brady Eidson  <beidson@apple.com>
 
         Reviewed by Adam
index 95c7664f616cd0fd30fc15ab80a08d896b3f7ef0..8a27bb8f6d577dcf9f23421690a5aec3ede3e542 100644 (file)
@@ -1,11 +1,9 @@
 /*
- * This file is part of the DOM implementation for KDE.
- *
  * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
  *               1999 Waldo Bastian (bastian@kde.org)
  *               2001 Andreas Schlapbach (schlpbch@iam.unibe.ch)
  *               2001-2003 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2002, 2006 Apple Computer, Inc.
+ * Copyright (C) 2002, 2006, 2007 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -214,14 +212,18 @@ bool CSSSelector::operator==(const CSSSelector& other)
 
 String CSSSelector::selectorText() const
 {
-    // FIXME: Support namespaces when dumping the selector text. -dwh
-    String str;
-    const CSSSelector* cs = this;
-    const AtomicString& localName = cs->m_tag.localName();
+    String str = "";
 
-    if (cs->m_match == CSSSelector::None || localName != starAtom)
-        str = localName;
+    const AtomicString& prefix = m_tag.prefix();
+    const AtomicString& localName = m_tag.localName();
+    if (m_match == CSSSelector::None || !prefix.isNull() || localName != starAtom) {
+        if (prefix.isNull())
+            str = localName;
+        else
+            str = prefix + "|" + localName;
+    }
 
+    const CSSSelector* cs = this;
     while (true) {
         if (cs->m_match == CSSSelector::Id) {
             str += "#";
@@ -232,14 +234,23 @@ String CSSSelector::selectorText() const
         } else if (cs->m_match == CSSSelector::PseudoClass) {
             str += ":";
             str += cs->m_value;
+            if (cs->pseudoType() == PseudoNot) {
+                if (CSSSelector* subSel = cs->m_simpleSelector)
+                    str += subSel->selectorText();
+                str += ")";
+            } else if (cs->pseudoType() == PseudoLang) {
+                str += cs->m_argument;
+                str += ")";
+            }
         } else if (cs->m_match == CSSSelector::PseudoElement) {
             str += "::";
             str += cs->m_value;
         } else if (cs->hasAttribute()) {
-            // FIXME: Add support for dumping namespaces.
-            String attrName = cs->m_attr.localName();
             str += "[";
-            str += attrName;
+            const AtomicString& prefix = cs->m_attr.prefix();
+            if (!prefix.isNull())
+                str += prefix + "|";
+            str += cs->m_attr.localName();
             switch (cs->m_match) {
                 case CSSSelector::Exact:
                     str += "=";