2010-06-11 Luiz Agostini <luiz.agostini@openbossa.org>, Kenneth Rohde Christiansen...
authoreric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 11 Jun 2010 14:25:44 +0000 (14:25 +0000)
committereric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 11 Jun 2010 14:25:44 +0000 (14:25 +0000)
        Reviewed by Antti Koivisto.

        CSS3 Media Queries are not serialized according to CSSOM
        https://bugs.webkit.org/show_bug.cgi?id=39220

        Added test for testing the serialization, plus updated current
        tests to take serialization into account.

        * fast/css/insertRule-media-expected.txt:
        * fast/css/insertRule-media.html:
        * fast/css/resources/insertRule-media.js:
        * fast/media/media-query-serialization-expected.txt: Added.
        * fast/media/media-query-serialization.html: Added.
2010-06-11  Luiz Agostini  <luiz.agostini@openbossa.org>

        Reviewed by Antti Koivisto.

        CSS3 Media Queries are not serialized according to CSSOM
        https://bugs.webkit.org/show_bug.cgi?id=39220

        MediaQuery serialization according to specification
        http://dev.w3.org/csswg/cssom/#serializing-media-queries.

        MediaQuery objects now ignore duplicated expressions. MediaQueryEvaluator::eval()
        now does not proccess MediaQuery objects that are known to be invalid.

        Test: fast/media/media-query-serialization.html

        * css/MediaQuery.cpp:
        (WebCore::stringCompare):
        (WebCore::MediaQuery::serialize):
        (WebCore::MediaQuery::MediaQuery):
        (WebCore::MediaQuery::~MediaQuery):
        (WebCore::MediaQuery::operator==):
        (WebCore::MediaQuery::cssText):
        (WebCore::MediaQuery::append):
        * css/MediaQuery.h:
        (WebCore::MediaQuery::ignored):
        (WebCore::MediaQuery::begin):
        (WebCore::MediaQuery::end):
        * css/MediaQueryExp.cpp:
        (WebCore::MediaQueryExp::serialize):
        * css/MediaQueryExp.h:
        * css/MediaQueryEvaluator.cpp:
        (WebCore::MediaQueryEvaluator::eval):

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

12 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css/insertRule-media-expected.txt
LayoutTests/fast/css/insertRule-media.html
LayoutTests/fast/css/resources/insertRule-media.js
LayoutTests/fast/media/media-query-serialization-expected.txt [new file with mode: 0644]
LayoutTests/fast/media/media-query-serialization.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/css/MediaQuery.cpp
WebCore/css/MediaQuery.h
WebCore/css/MediaQueryEvaluator.cpp
WebCore/css/MediaQueryExp.cpp
WebCore/css/MediaQueryExp.h

index 6c5c9974855c57581ad92b051b6f7d362ac7b9bf..6c0ec188070722d1e0819c28e4e48679b96534cf 100644 (file)
@@ -1,3 +1,19 @@
+2010-06-11  Luiz Agostini  <luiz.agostini@openbossa.org>, Kenneth Rohde Christiansen <kenneth@webkit.org>
+
+        Reviewed by Antti Koivisto.
+
+        CSS3 Media Queries are not serialized according to CSSOM
+        https://bugs.webkit.org/show_bug.cgi?id=39220
+
+        Added test for testing the serialization, plus updated current
+        tests to take serialization into account.
+
+        * fast/css/insertRule-media-expected.txt:
+        * fast/css/insertRule-media.html:
+        * fast/css/resources/insertRule-media.js:
+        * fast/media/media-query-serialization-expected.txt: Added.
+        * fast/media/media-query-serialization.html: Added.
+
 2010-06-10  Pavel Feldman  <pfeldman@chromium.org>
 
         Reviewed by Yury Semikhatsky.
index 51eaccd1396e13baaaa52344e2d0204dddee6135..53362366b8d1cc47cfb303ef093a7716427d583b 100644 (file)
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS document.styleSheets[0].insertRule(rule, 0) is 0
-PASS document.styleSheets[0].rules[0].cssText is rule
+PASS document.styleSheets[0].rules[0].cssText is serializedRule
 PASS successfullyParsed is true
 
 TEST COMPLETE
index de8f1d63ededf407c7baf53dfbdef1b0916fe300..83c2521ec3ba43c91f8ed9f51db10b8836ee2f3d 100644 (file)
@@ -1,6 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
 <html>
 <head>
+<link rel="help" href="http://dev.w3.org/csswg/cssom/#serialize-a-list-of-media-queries" />
 <style type="text/css"></style>
 <link rel="stylesheet" href="../js/resources/js-test-style.css">
 <script src="../js/resources/js-test-pre.js"></script>
index 9b6d40a76a1bb9fc9525579d428243e5c935dce9..7f532c083335a925456c81a1d417640c2924dd52 100644 (file)
@@ -3,7 +3,8 @@ description(
 );
 
 var rule = "@media all and (min-width: 0px) { \n  #greenid { color: green; }\n}";
+var serializedRule = "@media (min-width: 0px) { \n  #greenid { color: green; }\n}";
 shouldBe("document.styleSheets[0].insertRule(rule, 0)", "0");
-shouldBe("document.styleSheets[0].rules[0].cssText", "rule");
+shouldBe("document.styleSheets[0].rules[0].cssText", "serializedRule");
 
 var successfullyParsed = true;
diff --git a/LayoutTests/fast/media/media-query-serialization-expected.txt b/LayoutTests/fast/media/media-query-serialization-expected.txt
new file mode 100644 (file)
index 0000000..9f30f60
--- /dev/null
@@ -0,0 +1,10 @@
+Test media query serialization. https://bugs.webkit.org/show_bug.cgi?id=39220
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.styleSheets[0].media.mediaText is expected
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/media/media-query-serialization.html b/LayoutTests/fast/media/media-query-serialization.html
new file mode 100644 (file)
index 0000000..c2bae56
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="help" href="http://dev.w3.org/csswg/cssom/" />
+<style type="text/css" media="NOT braille, tv and (orientation: 'landscape') AND (min-WIDTH:100px) and (max-width: 200px ), all and (color) and (color)">
+</style>
+<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(
+'Test media query serialization.  <a href="https://bugs.webkit.org/show_bug.cgi?id=39220">https://bugs.webkit.org/show_bug.cgi?id=39220</a>'
+);
+
+
+var expected = "not braille, tv and (max-width: 200px) and (min-width: 100px) and (orientation: landscape), (color)";
+shouldBe("document.styleSheets[0].media.mediaText", "expected");
+
+var successfullyParsed = true;
+
+</script>
+
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
index 87340eee65ec0189c60e7e8c56bd2ffec22dcab4..b9019095d4d7a93e3a76eed3d71275c440f1b691 100644 (file)
@@ -1,3 +1,37 @@
+2010-06-11  Luiz Agostini  <luiz.agostini@openbossa.org>
+
+        Reviewed by Antti Koivisto.
+
+        CSS3 Media Queries are not serialized according to CSSOM
+        https://bugs.webkit.org/show_bug.cgi?id=39220
+
+        MediaQuery serialization according to specification
+        http://dev.w3.org/csswg/cssom/#serializing-media-queries.
+
+        MediaQuery objects now ignore duplicated expressions. MediaQueryEvaluator::eval()
+        now does not proccess MediaQuery objects that are known to be invalid.
+
+        Test: fast/media/media-query-serialization.html
+
+        * css/MediaQuery.cpp:
+        (WebCore::stringCompare):
+        (WebCore::MediaQuery::serialize):
+        (WebCore::MediaQuery::MediaQuery):
+        (WebCore::MediaQuery::~MediaQuery):
+        (WebCore::MediaQuery::operator==):
+        (WebCore::MediaQuery::cssText):
+        (WebCore::MediaQuery::append):
+        * css/MediaQuery.h:
+        (WebCore::MediaQuery::ignored):
+        (WebCore::MediaQuery::begin):
+        (WebCore::MediaQuery::end):
+        * css/MediaQueryExp.cpp:
+        (WebCore::MediaQueryExp::serialize):
+        * css/MediaQueryExp.h:
+        * css/MediaQueryEvaluator.cpp:
+        (WebCore::MediaQueryEvaluator::eval):
+
+
 2010-06-10  Jeremy Orlow  <jorlow@chromium.org>
 
         Reviewed by Steve Block.
index ff57372672f6b62140250ec97fdf530f5dfe347b..187a33d7ec004fb99cbf4a6e751ab24797f7517c 100644 (file)
@@ -2,6 +2,7 @@
  * CSS Media Query
  *
  * Copyright (C) 2005, 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "MediaQuery.h"
 
 #include "MediaQueryExp.h"
+#include "StringBuilder.h"
+
+#include <algorithm>
 
 namespace WebCore {
 
-MediaQuery::MediaQuery(Restrictor r, const String& mediaType, Vector<MediaQueryExp*>* exprs)
+// http://dev.w3.org/csswg/cssom/#serialize-a-media-query
+String MediaQuery::serialize() const
+{
+    StringBuilder result;
+
+    switch (m_restrictor) {
+    case MediaQuery::Only:
+        result.append("only ");
+        break;
+    case MediaQuery::Not:
+        result.append("not ");
+        break;
+    case MediaQuery::None:
+        break;
+    }
+
+    if (m_expressions->isEmpty()) {
+        result.append(m_mediaType);
+        return result.toString();
+    }
+
+    if (m_mediaType != "all" || m_restrictor != None) {
+        result.append(m_mediaType);
+        result.append(" and ");
+    }
+
+    result.append(m_expressions->at(0)->serialize());
+    for (size_t i = 1; i < m_expressions->size(); ++i) {
+        result.append(" and ");
+        result.append(m_expressions->at(i)->serialize());
+    }
+    return result.toString();
+}
+
+static bool expressionCompare(const MediaQueryExp* a, const MediaQueryExp* b)
+{
+    return codePointCompare(a->serialize(), b->serialize()) < 0;
+}
+
+MediaQuery::MediaQuery(Restrictor r, const String& mediaType, PassOwnPtr<Vector<MediaQueryExp*> > exprs)
     : m_restrictor(r)
-    , m_mediaType(mediaType)
-    , m_expressions(exprs)
+    , m_mediaType(mediaType.lower())
+    , m_expressions(exprs.release())
+    , m_ignored(false)
 {
-    if (!m_expressions)
+    if (!m_expressions) {
         m_expressions = new Vector<MediaQueryExp*>;
+        return;
+    }
+
+    std::sort(m_expressions->begin(), m_expressions->end(), expressionCompare);
+
+    // remove all duplicated expressions
+    String key;
+    for (int i = m_expressions->size() - 1; i >= 0; --i) {
+
+        // if not all of the expressions is valid the media query must be ignored.
+        if (!m_ignored)
+            m_ignored = !m_expressions->at(i)->isValid();
+
+        if (m_expressions->at(i)->serialize() == key) {
+            MediaQueryExp* item = m_expressions->at(i);
+            m_expressions->remove(i);
+            delete item;
+        } else
+            key = m_expressions->at(i)->serialize();
+    }
 }
 
 MediaQuery::~MediaQuery()
 {
-    if (m_expressions) {
-        deleteAllValues(*m_expressions);
-        delete m_expressions;
-    }
+    deleteAllValues(*m_expressions);
+    delete m_expressions;
 }
 
+// http://dev.w3.org/csswg/cssom/#compare-media-queries
 bool MediaQuery::operator==(const MediaQuery& other) const
 {
-    if (m_restrictor != other.m_restrictor
-        || m_mediaType != other.m_mediaType
-        || m_expressions->size() != other.m_expressions->size())
-        return false;
-
-    for (size_t i = 0; i < m_expressions->size(); ++i) {
-        MediaQueryExp* exp = m_expressions->at(i);
-        MediaQueryExp* oexp = other.m_expressions->at(i);
-        if (!(*exp == *oexp))
-            return false;
-    }
-
-    return true;
+    return cssText() == other.cssText();
 }
 
+// http://dev.w3.org/csswg/cssom/#serialize-a-list-of-media-queries
 String MediaQuery::cssText() const
 {
-    String text;
-    switch (m_restrictor) {
-        case MediaQuery::Only:
-            text += "only ";
-            break;
-        case MediaQuery::Not:
-            text += "not ";
-            break;
-        case MediaQuery::None:
-        default:
-            break;
-    }
-    text += m_mediaType;
-    for (size_t i = 0; i < m_expressions->size(); ++i) {
-        MediaQueryExp* exp = m_expressions->at(i);
-        text += " and (";
-        text += exp->mediaFeature();
-        if (exp->value()) {
-            text += ": ";
-            text += exp->value()->cssText();
-        }
-        text += ")";
-    }
-    return text;
+    if (m_serializationCache.isNull())
+        const_cast<MediaQuery*>(this)->m_serializationCache = serialize();
+
+    return m_serializationCache;
 }
 
 } //namespace
index 7cbd3bfa39020a6409894b90f6aa9371911dbcec..ccc59ac046af16713c96c96a13c0c59cbfa90355 100644 (file)
@@ -2,6 +2,7 @@
  * CSS Media Query
  *
  * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,7 +30,9 @@
 #define MediaQuery_h
 
 #include "PlatformString.h"
+#include <wtf/PassOwnPtr.h>
 #include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
 
 namespace WebCore {
 class MediaQueryExp;
@@ -40,20 +43,24 @@ public:
         Only, Not, None
     };
 
-    MediaQuery(Restrictor r, const String& mediaType, Vector<MediaQueryExp*>* exprs);
+    MediaQuery(Restrictor r, const String& mediaType, PassOwnPtr<Vector<MediaQueryExp*> > exprs);
     ~MediaQuery();
 
     Restrictor restrictor() const { return m_restrictor; }
     const Vector<MediaQueryExp*>* expressions() const { return m_expressions; }
     String mediaType() const { return m_mediaType; }
     bool operator==(const MediaQuery& other) const;
-    void append(MediaQueryExp* newExp) { m_expressions->append(newExp); }
     String cssText() const;
+    bool ignored() const { return m_ignored; }
 
  private:
     Restrictor m_restrictor;
     String m_mediaType;
     Vector<MediaQueryExp*>* m_expressions;
+    bool m_ignored;
+    String m_serializationCache;
+
+    String serialize() const;
 };
 
 } // namespace
index 20c7bb98f950212513286853faa389faab2dae38..9d5822fd95b4c391f016161c7a30951c61e60b8d 100644 (file)
@@ -144,6 +144,9 @@ bool MediaQueryEvaluator::eval(const MediaList* mediaList, CSSStyleSelector* sty
     for (size_t i = 0; i < queries.size() && !result; ++i) {
         MediaQuery* query = queries.at(i);
 
+        if (query->ignored())
+            continue;
+
         if (mediaTypeMatch(query->mediaType())) {
             const Vector<MediaQueryExp*>* exps = query->expressions();
             // iterate through expressions, stop if any of them eval to false
index 53c0b73b4fe29aaf90887e964f3c6f1ab4ebaf13..a93ddcce579423574bdd3979f80c4ceb0bb0c4fc 100644 (file)
@@ -2,6 +2,7 @@
  * CSS Media Query
  *
  * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,6 +32,7 @@
 #include "CSSParser.h"
 #include "CSSPrimitiveValue.h"
 #include "CSSValueList.h"
+#include "StringBuilder.h"
 
 namespace WebCore {
 
@@ -82,4 +84,22 @@ MediaQueryExp::~MediaQueryExp()
 {
 }
 
+String MediaQueryExp::serialize() const
+{
+    if (!m_serializationCache.isNull())
+        return m_serializationCache;
+
+    StringBuilder result;
+    result.append("(");
+    result.append(m_mediaFeature.lower());
+    if (m_value) {
+        result.append(": ");
+        result.append(m_value->cssText());
+    }
+    result.append(")");
+
+    const_cast<MediaQueryExp*>(this)->m_serializationCache = result.toString();
+    return m_serializationCache;
+}
+
 } // namespace
index 92724020aaf056339f025ab27a4784db27674a07..24f2207332fb1e572419cb147170cc9b408e1e2b 100644 (file)
@@ -2,6 +2,7 @@
  * CSS Media Query
  *
  * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,10 +65,14 @@ public:
                                               m_mediaFeature == MediaFeatureNames::aspect_ratioMediaFeature ||
                                               m_mediaFeature == MediaFeatureNames::min_aspect_ratioMediaFeature ||
                                               m_mediaFeature == MediaFeatureNames::max_aspect_ratioMediaFeature;  }
+
+    String serialize() const;
+
 private:
     AtomicString m_mediaFeature;
     RefPtr<CSSValue> m_value;
     bool m_isValid;
+    String m_serializationCache;
 };
 
 } // namespace