* fast/dom/Range/range-clone-empty.html: Added.
* fast/dom/Range/resources/range-clone-empty.js: Added.
+2008-01-06 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ Make attr selectors case-insensitive for certain HTML attributes
+ http://bugs.webkit.org/show_bug.cgi?id=15470
+
+ * fast/css/html-attr-case-sensitivity-expected.txt: Added.
+ * fast/css/html-attr-case-sensitivity.html: Added.
+ * fast/css/resources/html-attr-case-sensitivity.js: Added.
+
2008-01-06 Eric Seidel <eric@webkit.org>
Reviewed by Sam.
--- /dev/null
+This tests that [attr=value] CSS selectors are case sensitive depending on attr
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS isCaseSensitive("abbr") is true
+PASS isCaseSensitive("accept-charset") is false
+PASS isCaseSensitive("accept") is false
+PASS isCaseSensitive("accesskey") is true
+PASS isCaseSensitive("action") is true
+PASS isCaseSensitive("align") is false
+PASS isCaseSensitive("alink") is false
+PASS isCaseSensitive("alt") is true
+PASS isCaseSensitive("archive") is true
+PASS isCaseSensitive("axis") is false
+PASS isCaseSensitive("background") is true
+PASS isCaseSensitive("bgcolor") is false
+PASS isCaseSensitive("border") is true
+PASS isCaseSensitive("cellpadding") is true
+PASS isCaseSensitive("cellspacing") is true
+PASS isCaseSensitive("char") is true
+PASS isCaseSensitive("charoff") is true
+PASS isCaseSensitive("charset") is false
+PASS isCaseSensitive("checked") is false
+PASS isCaseSensitive("cite") is true
+PASS isCaseSensitive("class") is true
+PASS isCaseSensitive("classid") is true
+PASS isCaseSensitive("clear") is false
+PASS isCaseSensitive("code") is true
+PASS isCaseSensitive("codebase") is true
+PASS isCaseSensitive("codetype") is false
+PASS isCaseSensitive("color") is false
+PASS isCaseSensitive("cols") is true
+PASS isCaseSensitive("colspan") is true
+PASS isCaseSensitive("compact") is false
+PASS isCaseSensitive("content") is true
+PASS isCaseSensitive("coords") is true
+PASS isCaseSensitive("data") is true
+PASS isCaseSensitive("datetime") is true
+PASS isCaseSensitive("declare") is false
+PASS isCaseSensitive("defer") is false
+PASS isCaseSensitive("dir") is false
+PASS isCaseSensitive("disabled") is false
+PASS isCaseSensitive("enctype") is false
+PASS isCaseSensitive("face") is false
+PASS isCaseSensitive("for") is true
+PASS isCaseSensitive("frame") is false
+PASS isCaseSensitive("frameborder") is true
+PASS isCaseSensitive("headers") is true
+PASS isCaseSensitive("height") is true
+PASS isCaseSensitive("href") is true
+PASS isCaseSensitive("hreflang") is false
+PASS isCaseSensitive("hspace") is true
+PASS isCaseSensitive("http-equiv") is false
+PASS isCaseSensitive("id") is true
+PASS isCaseSensitive("ismap") is true
+PASS isCaseSensitive("label") is true
+PASS isCaseSensitive("lang") is false
+PASS isCaseSensitive("language") is false
+PASS isCaseSensitive("link") is false
+PASS isCaseSensitive("longdesc") is true
+PASS isCaseSensitive("marginheight") is true
+PASS isCaseSensitive("marginwidth") is true
+PASS isCaseSensitive("maxlength") is true
+PASS isCaseSensitive("media") is false
+PASS isCaseSensitive("method") is false
+PASS isCaseSensitive("multiple") is false
+PASS isCaseSensitive("name") is true
+PASS isCaseSensitive("nohref") is false
+PASS isCaseSensitive("noresize") is false
+PASS isCaseSensitive("noshade") is false
+PASS isCaseSensitive("nowrap") is false
+PASS isCaseSensitive("object") is true
+PASS isCaseSensitive("onblur") is true
+PASS isCaseSensitive("onchange") is true
+PASS isCaseSensitive("onclick") is true
+PASS isCaseSensitive("ondblclick") is true
+PASS isCaseSensitive("onfocus") is true
+PASS isCaseSensitive("onkeydown") is true
+PASS isCaseSensitive("onkeypress") is true
+PASS isCaseSensitive("onkeyup") is true
+PASS isCaseSensitive("onload") is true
+PASS isCaseSensitive("onmousedown") is true
+PASS isCaseSensitive("onmousemove") is true
+PASS isCaseSensitive("onmouseout") is true
+PASS isCaseSensitive("onmouseover") is true
+PASS isCaseSensitive("onmouseup") is true
+PASS isCaseSensitive("onreset") is true
+PASS isCaseSensitive("onselect") is true
+PASS isCaseSensitive("onsubmit") is true
+PASS isCaseSensitive("onunload") is true
+PASS isCaseSensitive("profile") is true
+PASS isCaseSensitive("prompt") is true
+PASS isCaseSensitive("readonly") is false
+PASS isCaseSensitive("rel") is false
+PASS isCaseSensitive("rev") is false
+PASS isCaseSensitive("rows") is true
+PASS isCaseSensitive("rowspan") is true
+PASS isCaseSensitive("rules") is false
+PASS isCaseSensitive("scheme") is true
+PASS isCaseSensitive("scope") is false
+PASS isCaseSensitive("scrolling") is false
+PASS isCaseSensitive("selected") is false
+PASS isCaseSensitive("shape") is false
+PASS isCaseSensitive("size") is true
+PASS isCaseSensitive("span") is true
+PASS isCaseSensitive("src") is true
+PASS isCaseSensitive("standby") is true
+PASS isCaseSensitive("start") is true
+PASS isCaseSensitive("style") is true
+PASS isCaseSensitive("summary") is true
+PASS isCaseSensitive("tabindex") is true
+PASS isCaseSensitive("target") is false
+PASS isCaseSensitive("text") is false
+PASS isCaseSensitive("title") is true
+PASS isCaseSensitive("type") is false
+PASS isCaseSensitive("usemap") is true
+PASS isCaseSensitive("valign") is false
+PASS isCaseSensitive("value") is true
+PASS isCaseSensitive("valuetype") is false
+PASS isCaseSensitive("version") is true
+PASS isCaseSensitive("vlink") is false
+PASS isCaseSensitive("vspace") is true
+PASS isCaseSensitive("width") is true
+PASS isCaseSensitive("foobar") is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<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 src="resources/html-attr-case-sensitivity.js"></script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+description("This tests that [attr=value] CSS selectors are case sensitive depending on attr");
+
+// List of all HTML4 attrs
+// true = case sensitive
+var htmlAttrs = {
+ "abbr" : true,
+ "accept-charset" : false,
+ "accept" : false,
+ "accesskey" : true,
+ "action" : true,
+ "align" : false,
+ "alink" : false,
+ "alt" : true,
+ "archive" : true,
+ "axis" : false,
+ "background" : true,
+ "bgcolor" : false,
+ "border" : true,
+ "cellpadding" : true,
+ "cellspacing" : true,
+ "char" : true,
+ "charoff" : true,
+ "charset" : false,
+ "checked" : false,
+ "cite" : true,
+ "class" : true,
+ "classid" : true,
+ "clear" : false,
+ "code" : true,
+ "codebase" : true,
+ "codetype" : false,
+ "color" : false,
+ "cols" : true,
+ "colspan" : true,
+ "compact" : false,
+ "content" : true,
+ "coords" : true,
+ "data" : true,
+ "datetime" : true,
+ "declare" : false,
+ "defer" : false,
+ "dir" : false,
+ "disabled" : false,
+ "enctype" : false,
+ "face" : false,
+ "for" : true,
+ "frame" : false,
+ "frameborder" : true,
+ "headers" : true,
+ "height" : true,
+ "href" : true,
+ "hreflang" : false,
+ "hspace" : true,
+ "http-equiv" : false,
+ "id" : true,
+ "ismap" : true,
+ "label" : true,
+ "lang" : false,
+ "language" : false,
+ "link" : false,
+ "longdesc" : true,
+ "marginheight" : true,
+ "marginwidth" : true,
+ "maxlength" : true,
+ "media" : false,
+ "method" : false,
+ "multiple" : false,
+ "name" : true,
+ "nohref" : false,
+ "noresize" : false,
+ "noshade" : false,
+ "nowrap" : false,
+ "object" : true,
+ "onblur" : true,
+ "onchange" : true,
+ "onclick" : true,
+ "ondblclick" : true,
+ "onfocus" : true,
+ "onkeydown" : true,
+ "onkeypress" : true,
+ "onkeyup" : true,
+ "onload" : true,
+ "onmousedown" : true,
+ "onmousemove" : true,
+ "onmouseout" : true,
+ "onmouseover" : true,
+ "onmouseup" : true,
+ "onreset" : true,
+ "onselect" : true,
+ "onsubmit" : true,
+ "onunload" : true,
+ "profile" : true,
+ "prompt" : true,
+ "readonly" : false,
+ "rel" : false,
+ "rev" : false,
+ "rows" : true,
+ "rowspan" : true,
+ "rules" : false,
+ "scheme" : true,
+ "scope" : false,
+ "scrolling" : false,
+ "selected" : false,
+ "shape" : false,
+ "size" : true,
+ "span" : true,
+ "src" : true,
+ "standby" : true,
+ "start" : true,
+ "style" : true,
+ "summary" : true,
+ "tabindex" : true,
+ "target" : false,
+ "text" : false,
+ "title" : true,
+ "type" : false,
+ "usemap" : true,
+ "valign" : false,
+ "value" : true,
+ "valuetype" : false,
+ "version" : true,
+ "vlink" : false,
+ "vspace" : true,
+ "width" : true
+};
+
+function isCaseSensitive(attrName) {
+ var style = document.createElement('style');
+ style.appendChild(document.createTextNode("br { color: red; float: right; border-color: red; }\n"));
+ style.appendChild(document.createTextNode("br[" + attrName + "=foo] { color: blue; }\n"));
+ style.appendChild(document.createTextNode("br[" + attrName + "~=foo] { float: left; }\n"));
+ style.appendChild(document.createTextNode("br[" + attrName + "|=foo] { border-left-color: green; }\n"));
+ style.appendChild(document.createTextNode("br[" + attrName + "^=foo] { border-right-color: pink; }\n"));
+ style.appendChild(document.createTextNode("br[" + attrName + "$=foo] { border-top-color: orange; }\n"));
+ style.appendChild(document.createTextNode("br[" + attrName + "*=foo] { border-bottom-color: black; }\n"));
+
+ document.documentElement.firstChild.appendChild(style);
+
+ var testElement = document.createElement("br");
+ testElement.setAttribute(attrName, "FOO");
+ document.body.appendChild(testElement);
+
+ var computedStyle = window.getComputedStyle(testElement, '');
+
+ var isCaseInsensitive = (computedStyle.getPropertyValue("color") == "rgb(0, 0, 255)");
+
+ if ((computedStyle.getPropertyValue("float") == "left") != isCaseInsensitive)
+ testFailed("~=foo and =foo for " + attrName + " did not match with same case sensitivity");
+
+ if ((computedStyle.getPropertyValue("border-left-color") == "rgb(0, 128, 0)") != isCaseInsensitive)
+ testFailed("|=foo and =foo for " + attrName + " did not match with same case sensitivity");
+
+ if ((computedStyle.getPropertyValue("border-right-color") == "rgb(255, 192, 203)") != isCaseInsensitive)
+ testFailed("^=foo and =foo for " + attrName + " did not match with same case sensitivity");
+
+ if ((computedStyle.getPropertyValue("border-top-color") == "rgb(255, 165, 0)") != isCaseInsensitive)
+ testFailed("$=foo and =foo for " + attrName + " did not match with same case sensitivity");
+
+ if ((computedStyle.getPropertyValue("border-bottom-color") == "rgb(0, 0, 0)") != isCaseInsensitive)
+ testFailed("*=foo and =foo for " + attrName + " did not match with same case sensitivity");
+
+ // clean up
+ testElement.parentNode.removeChild(testElement);
+ style.parentNode.removeChild(style);
+
+ return !isCaseInsensitive;
+}
+
+for (var attr in htmlAttrs) {
+ shouldBe('isCaseSensitive("' + attr + '")', "" + htmlAttrs[attr]);
+}
+
+// test a nonexistent attr
+shouldBe('isCaseSensitive("foobar")', "true");
+
+var successfullyParsed = true;
* html/CanvasPattern.cpp:
(WebCore::CanvasPattern::CanvasPattern):
+2008-01-06 Eric Seidel <eric@webkit.org>
+
+ Reviewed by darin.
+
+ Make attr selectors case-insensitive for certain HTML attributes
+ http://bugs.webkit.org/show_bug.cgi?id=15470
+
+ Test: fast/css/html-attr-case-sensitivity.html
+
+ * css/CSSStyleSelector.cpp:
+ (WebCore::addLocalNameToSet):
+ (WebCore::createHtmlCaseInsensitiveAttributesSet):
+ (WebCore::htmlAttributeHasCaseInsensitiveValue):
+ (WebCore::CSSStyleSelector::checkOneSelector):
+
2008-01-06 Eric Seidel <eric@webkit.org>
Reviewed by Sam.
return SelectorFailsCompletely;
}
+static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName)
+{
+ set->add(qName.localName().impl());
+}
+
+static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet()
+{
+ // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
+ // Mozilla treats all other values as case-sensitive, thus so do we.
+ HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>;
+
+ addLocalNameToSet(attrSet, accept_charsetAttr);
+ addLocalNameToSet(attrSet, acceptAttr);
+ addLocalNameToSet(attrSet, alignAttr);
+ addLocalNameToSet(attrSet, alinkAttr);
+ addLocalNameToSet(attrSet, axisAttr);
+ addLocalNameToSet(attrSet, bgcolorAttr);
+ addLocalNameToSet(attrSet, charsetAttr);
+ addLocalNameToSet(attrSet, checkedAttr);
+ addLocalNameToSet(attrSet, clearAttr);
+ addLocalNameToSet(attrSet, codetypeAttr);
+ addLocalNameToSet(attrSet, colorAttr);
+ addLocalNameToSet(attrSet, compactAttr);
+ addLocalNameToSet(attrSet, declareAttr);
+ addLocalNameToSet(attrSet, deferAttr);
+ addLocalNameToSet(attrSet, dirAttr);
+ addLocalNameToSet(attrSet, disabledAttr);
+ addLocalNameToSet(attrSet, enctypeAttr);
+ addLocalNameToSet(attrSet, faceAttr);
+ addLocalNameToSet(attrSet, frameAttr);
+ addLocalNameToSet(attrSet, hreflangAttr);
+ addLocalNameToSet(attrSet, http_equivAttr);
+ addLocalNameToSet(attrSet, langAttr);
+ addLocalNameToSet(attrSet, languageAttr);
+ addLocalNameToSet(attrSet, linkAttr);
+ addLocalNameToSet(attrSet, mediaAttr);
+ addLocalNameToSet(attrSet, methodAttr);
+ addLocalNameToSet(attrSet, multipleAttr);
+ addLocalNameToSet(attrSet, nohrefAttr);
+ addLocalNameToSet(attrSet, noresizeAttr);
+ addLocalNameToSet(attrSet, noshadeAttr);
+ addLocalNameToSet(attrSet, nowrapAttr);
+ addLocalNameToSet(attrSet, readonlyAttr);
+ addLocalNameToSet(attrSet, relAttr);
+ addLocalNameToSet(attrSet, revAttr);
+ addLocalNameToSet(attrSet, rulesAttr);
+ addLocalNameToSet(attrSet, scopeAttr);
+ addLocalNameToSet(attrSet, scrollingAttr);
+ addLocalNameToSet(attrSet, selectedAttr);
+ addLocalNameToSet(attrSet, shapeAttr);
+ addLocalNameToSet(attrSet, targetAttr);
+ addLocalNameToSet(attrSet, textAttr);
+ addLocalNameToSet(attrSet, typeAttr);
+ addLocalNameToSet(attrSet, valignAttr);
+ addLocalNameToSet(attrSet, valuetypeAttr);
+ addLocalNameToSet(attrSet, vlinkAttr);
+
+ return attrSet;
+}
+
+static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr)
+{
+ static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
+ bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom);
+ return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl());
+}
+
bool CSSStyleSelector::checkOneSelector(CSSSelector* sel, Element* e, bool isAncestor, bool isSubSelector)
{
if (!e)
if (value.isNull())
return false; // attribute is not set
+ bool caseSensitive = isXMLDoc || !htmlAttributeHasCaseInsensitiveValue(sel->m_attr);
+
switch (sel->m_match) {
case CSSSelector::Exact:
- if ((isXMLDoc && sel->m_value != value) || (!isXMLDoc && !equalIgnoringCase(sel->m_value, value)))
+ if (caseSensitive ? sel->m_value != value : !equalIgnoringCase(sel->m_value, value))
return false;
break;
case CSSSelector::List:
int startSearchAt = 0;
while (true) {
- int foundPos = value.find(sel->m_value, startSearchAt, isXMLDoc);
+ int foundPos = value.find(sel->m_value, startSearchAt, caseSensitive);
if (foundPos == -1)
return false;
if (foundPos == 0 || value[foundPos-1] == ' ') {
break;
}
case CSSSelector::Contain:
- if (!value.contains(sel->m_value, isXMLDoc))
+ if (!value.contains(sel->m_value, caseSensitive))
return false;
break;
case CSSSelector::Begin:
- if (!value.startsWith(sel->m_value, isXMLDoc))
+ if (!value.startsWith(sel->m_value, caseSensitive))
return false;
break;
case CSSSelector::End:
- if (!value.endsWith(sel->m_value, isXMLDoc))
+ if (!value.endsWith(sel->m_value, caseSensitive))
return false;
break;
case CSSSelector::Hyphen:
if (value.length() < sel->m_value.length())
return false;
- if (!value.startsWith(sel->m_value, isXMLDoc))
+ if (!value.startsWith(sel->m_value, caseSensitive))
return false;
// It they start the same, check for exact match or following '-':
if (value.length() != sel->m_value.length() && value[sel->m_value.length()] != '-')
break;
}
}
- if (sel->m_match == CSSSelector::PseudoClass)
- {
+ if (sel->m_match == CSSSelector::PseudoClass) {
switch (sel->pseudoType()) {
// Pseudo classes:
case CSSSelector::PseudoEmpty: