Bug 578714: Stop doing Unicode-aware case-folding inside layout/style. r=zwol sr=bz
authorKyle Huey <me@kylehuey.com>
Mon, 02 Aug 2010 15:19:04 -0700
changeset 48880 d59ad0384708fcb57463e32fc878f6576dd8cb7f
parent 48879 b22036de463abb4a9599467ed3ade634aee953c0
child 48881 6001758d1f47a8336e2a0257eda10781996a7859
push idunknown
push userunknown
push dateunknown
reviewerszwol, bz
bugs578714
milestone2.0b4pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 578714: Stop doing Unicode-aware case-folding inside layout/style. r=zwol sr=bz
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
intl/unicharutil/util/nsUnicharUtils.cpp
intl/unicharutil/util/nsUnicharUtils.h
layout/reftests/reftest.list
layout/reftests/unicode/reftest.list
layout/reftests/unicode/unicode-attribute-selector.html
layout/reftests/unicode/unicode-element-selector.html
layout/reftests/unicode/unicode-lang.html
layout/reftests/unicode/unicode-media-query-media-type.html
layout/reftests/unicode/unicode-media-query-query.html
layout/reftests/unicode/unicode-pseudo-selector.html
layout/reftests/unicode/unicode-ref-print.html
layout/reftests/unicode/unicode-ref.html
layout/style/nsCSSParser.cpp
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsCSSStyleRule.cpp
layout/style/nsRuleNode.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1492,22 +1492,24 @@ public:
    * case for ASCII characters a-z.
    */
   static PRBool EqualsIgnoreASCIICase(const nsAString& aStr1,
                                       const nsAString& aStr2);
 
   /**
    * Convert ASCII A-Z to a-z.
    */
+  static void ASCIIToLower(nsAString& aStr);
   static void ASCIIToLower(const nsAString& aSource, nsAString& aDest);
 
   /**
    * Convert ASCII a-z to A-Z.
    */
   static void ASCIIToUpper(nsAString& aStr);
+  static void ASCIIToUpper(const nsAString& aSource, nsAString& aDest);
 
   static nsIInterfaceRequestor* GetSameOriginChecker();
 
   static nsIThreadJSContextStack* ThreadJSContextStack()
   {
     return sThreadJSContextStack;
   }
   
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -5015,16 +5015,31 @@ nsContentUtils::GetCurrentJSContext()
 
   sThreadJSContextStack->Peek(&cx);
 
   return cx;
 }
 
 /* static */
 void
+nsContentUtils::ASCIIToLower(nsAString& aStr)
+{
+  PRUnichar* iter = aStr.BeginWriting();
+  PRUnichar* end = aStr.EndWriting();
+  while (iter != end) {
+    PRUnichar c = *iter;
+    if (c >= 'A' && c <= 'Z') {
+      *iter = c + ('a' - 'A');
+    }
+    ++iter;
+  }
+}
+
+/* static */
+void
 nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest)
 {
   PRUint32 len = aSource.Length();
   aDest.SetLength(len);
   if (aDest.Length() == len) {
     PRUnichar* dest = aDest.BeginWriting();
     const PRUnichar* iter = aSource.BeginReading();
     const PRUnichar* end = aSource.EndReading();
@@ -5048,16 +5063,36 @@ nsContentUtils::ASCIIToUpper(nsAString& 
     PRUnichar c = *iter;
     if (c >= 'a' && c <= 'z') {
       *iter = c + ('A' - 'a');
     }
     ++iter;
   }
 }
 
+/* static */
+void
+nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest)
+{
+  PRUint32 len = aSource.Length();
+  aDest.SetLength(len);
+  if (aDest.Length() == len) {
+    PRUnichar* dest = aDest.BeginWriting();
+    const PRUnichar* iter = aSource.BeginReading();
+    const PRUnichar* end = aSource.EndReading();
+    while (iter != end) {
+      PRUnichar c = *iter;
+      *dest = (c >= 'a' && c <= 'z') ?
+         c + ('A' - 'a') : c;
+      ++iter;
+      ++dest;
+    }
+  }
+}
+
 PRBool
 nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1,
                                       const nsAString& aStr2)
 {
   PRUint32 len = aStr1.Length();
   if (len != aStr2.Length()) {
     return PR_FALSE;
   }
--- a/intl/unicharutil/util/nsUnicharUtils.cpp
+++ b/intl/unicharutil/util/nsUnicharUtils.cpp
@@ -181,16 +181,24 @@ ToLowerCase(const nsAString& aSource,
   const PRUnichar *in;
   PRUnichar *out;
   PRUint32 len = NS_StringGetData(aSource, &in);
   NS_StringGetMutableData(aDest, len, &out);
   NS_ASSERTION(out, "Uh...");
   ToLowerCase(in, out, len);
 }
 
+PRUnichar
+ToLowerCaseASCII(const PRUnichar aChar)
+{
+  if (IS_ASCII_UPPER(aChar))
+    return aChar + 0x0020;
+  return aChar;
+}
+
 void
 ToUpperCase(nsAString& aString)
 {
   PRUnichar *buf = aString.BeginWriting();
   ToUpperCase(buf, buf, aString.Length());
 }
 
 void
@@ -229,16 +237,59 @@ nsCaseInsensitiveStringComparator::opera
   if (lhs == rhs)
     return 0;
   else if (lhs < rhs)
     return -1;
   else
     return 1;
 }
 
+PRInt32
+nsASCIICaseInsensitiveStringComparator::operator()(const PRUnichar* lhs,
+                                                   const PRUnichar* rhs,
+                                                   PRUint32 aLength) const
+{
+  while (aLength) {
+    PRUnichar l = *lhs++;
+    PRUnichar r = *rhs++;
+    if (l != r) {
+      l = ToLowerCaseASCII(l);
+      r = ToLowerCaseASCII(r);
+
+      if (l > r)
+        return 1;
+      else if (r > l)
+        return -1;
+    }
+    aLength--;
+  }
+
+  return 0;
+}
+
+PRInt32
+nsASCIICaseInsensitiveStringComparator::operator()(PRUnichar lhs,
+                                                   PRUnichar rhs) const
+{
+  // see if they're an exact match first
+  if (lhs == rhs)
+    return 0;
+  
+  lhs = ToLowerCaseASCII(lhs);
+  rhs = ToLowerCaseASCII(rhs);
+  
+  if (lhs == rhs)
+    return 0;
+  else if (lhs < rhs)
+    return -1;
+  else
+    return 1;
+}
+
+
 #endif // MOZILLA_INTERNAL_API
 
 PRInt32
 CaseInsensitiveCompare(const PRUnichar *a,
                        const PRUnichar *b,
                        PRUint32 len)
 {
   NS_ASSERTION(a && b, "Do not pass in invalid pointers!");
--- a/intl/unicharutil/util/nsUnicharUtils.h
+++ b/intl/unicharutil/util/nsUnicharUtils.h
@@ -87,16 +87,26 @@ class nsCaseInsensitiveStringArrayCompar
 {
 public:
   template<class A, class B>
   PRBool Equals(const A& a, const B& b) const {
     return a.Equals(b, nsCaseInsensitiveStringComparator());
   }
 };
 
+class nsASCIICaseInsensitiveStringComparator : public nsStringComparator
+{
+public:
+  virtual int operator() (const PRUnichar*,
+                          const PRUnichar*,
+                          PRUint32 aLength) const;
+  virtual int operator() (PRUnichar,
+                          PRUnichar) const;
+};
+
 inline PRBool
 CaseInsensitiveFindInReadable(const nsAString& aPattern,
                               nsAString::const_iterator& aSearchStart,
                               nsAString::const_iterator& aSearchEnd)
 {
   return FindInReadable(aPattern, aSearchStart, aSearchEnd,
                         nsCaseInsensitiveStringComparator());
 }
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -212,16 +212,19 @@ include text-shadow/reftest.list
 include ../../toolkit/themes/pinstripe/reftests/reftest.list
 
 # text-transform/
 include text-transform/reftest.list
 
 # -moz-transform/
 include transform/reftest.list
 
+# unicode/ (verify that we don't do expend effort doing unicode-aware case checks)
+include unicode/reftest.list
+
 # widget/
 include ../../widget/reftests/reftest.list
 
 # xml-stylesheet/
 include ../../content/test/reftest/xml-stylesheet/reftest.list
 
 # xul-document-load/
 include xul-document-load/reftest.list
new file mode 100644
--- /dev/null
+++ b/layout/reftests/unicode/reftest.list
@@ -0,0 +1,6 @@
+== unicode-attribute-selector.html unicode-ref.html
+== unicode-element-selector.html unicode-ref.html
+== unicode-lang.html unicode-ref.html
+== unicode-media-query-media-type.html unicode-ref-print.html
+== unicode-media-query-query.html unicode-ref-print.html
+== unicode-pseudo-selector.html unicode-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/unicode/unicode-attribute-selector.html
@@ -0,0 +1,19 @@
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Unicode tests - attribute selectors</title>
+  <style>
+    div[dİr] {color: red;}
+    div[dİr="ltr"] {text-indent: 30px;}
+    input[dİsabled] {display: none;}
+    //input[dİsabled="disabled"] {display: inline;}
+  </style>
+</head>
+
+<body>
+  <div dir='ltr'><p lang="hi">स्टार</p></div>
+  <input disabled>
+  <input dİsabled="DİSABLED">
+  <input dİsabled="disabled">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/unicode/unicode-element-selector.html
@@ -0,0 +1,14 @@
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Unicode tests - element selectors</title>
+  <style>
+    dİv {color: red}
+  </style>
+</head>
+
+<body>
+  <div><p lang="hi">स्टार</p></div>
+  <input disabled>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/unicode/unicode-lang.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Unicode tests - language selector</title>
+  <style>
+    p:lang(hİ) {color: red}
+    //p[lang="hİ"] {text-indent:30px} Disabled until Bug 492431 is fixed
+  </style>
+</head>
+
+<body>
+  <div><p lang="hi">स्टार</p></div>
+  <input disabled>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/unicode/unicode-media-query-media-type.html
@@ -0,0 +1,15 @@
+<html class="reftest-print">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Unicode tests - media query - media type selector</title>
+  <style>
+    @media prİnt {
+    p { color: red }
+    }
+  </style>
+</head>
+
+<body>
+  <div><p lang="hi">स्टार</p></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/unicode/unicode-media-query-query.html
@@ -0,0 +1,13 @@
+<html class="reftest-print">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Unicode tests - media query - media query text</title>
+  <style>
+    @media print and (mİn-wİdth: 5in) { p {color: red; } }
+  </style>
+</head>
+
+<body>
+  <div><p lang="hi">स्टार</p></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/unicode/unicode-pseudo-selector.html
@@ -0,0 +1,14 @@
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Unicode tests - pseudo element selectors</title>
+  <style>
+    p:fİrst-letter {color: red}
+  </style>
+</head>
+
+<body>
+  <div><p lang="hi">स्टार</p></div>
+  <input disabled>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/unicode/unicode-ref-print.html
@@ -0,0 +1,10 @@
+<html class="reftest-print">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Unicode tests - media query - reference</title>
+</head>
+
+<body>
+  <div><p lang="hi">स्टार</p></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/unicode/unicode-ref.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Unicode tests - reference rending</title>
+</head>
+
+<body>
+  <div><p lang="hi">स्टार</p></div>
+  <input disabled>
+</body>
+</html>
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -1623,17 +1623,17 @@ CSSParserImpl::ParseMediaQuery(PRUnichar
         return PR_FALSE;
       }
       if (eCSSToken_Ident != mToken.mType) {
         REPORT_UNEXPECTED_TOKEN(PEGatherMediaNotIdent);
         UngetToken();
         return PR_FALSE;
       }
       // case insensitive from CSS - must be lower cased
-      ToLowerCase(mToken.mIdent);
+      nsContentUtils::ASCIIToLower(mToken.mIdent);
       mediaType = do_GetAtom(mToken.mIdent);
       if (gotNotOrOnly ||
           (mediaType != nsGkAtoms::_not && mediaType != nsGkAtoms::only))
         break;
       gotNotOrOnly = PR_TRUE;
       if (mediaType == nsGkAtoms::_not)
         query->SetNegated();
       else
@@ -1741,17 +1741,17 @@ CSSParserImpl::ParseMediaQueryExpression
   nsMediaExpression *expr = aQuery->NewExpression();
   if (!expr) {
     mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
     SkipUntil(')');
     return PR_FALSE;
   }
 
   // case insensitive from CSS - must be lower cased
-  ToLowerCase(mToken.mIdent);
+  nsContentUtils::ASCIIToLower(mToken.mIdent);
   const PRUnichar *featureString;
   if (StringBeginsWith(mToken.mIdent, NS_LITERAL_STRING("min-"))) {
     expr->mRange = nsMediaExpression::eMin;
     featureString = mToken.mIdent.get() + 4;
   } else if (StringBeginsWith(mToken.mIdent, NS_LITERAL_STRING("max-"))) {
     expr->mRange = nsMediaExpression::eMax;
     featureString = mToken.mIdent.get() + 4;
   } else {
@@ -2894,17 +2894,17 @@ CSSParserImpl::ParseAttributeSelector(PR
               "type",
               // additional attributes not in HTML4
               "direction", // marquee
               nsnull
             };
             short i = 0;
             const char* htmlAttr;
             while ((htmlAttr = caseInsensitiveHTMLAttribute[i++])) {
-              if (attr.EqualsIgnoreCase(htmlAttr)) {
+              if (attr.LowerCaseEqualsASCII(htmlAttr)) {
                 isCaseSensitive = PR_FALSE;
                 break;
               }
             }
           }
           aDataMask |= SEL_MASK_ATTRIB;
           aSelector.AddAttribute(nameSpaceID, attr, func, value, isCaseSensitive);
         }
@@ -2968,17 +2968,17 @@ CSSParserImpl::ParsePseudoSelector(PRInt
     return eSelectorParsingStatus_Error;
   }
 
   // OK, now we know we have an mIdent.  Atomize it.  All the atoms, for
   // pseudo-classes as well as pseudo-elements, start with a single ':'.
   nsAutoString buffer;
   buffer.Append(PRUnichar(':'));
   buffer.Append(mToken.mIdent);
-  ToLowerCase(buffer);
+  nsContentUtils::ASCIIToLower(buffer);
   nsCOMPtr<nsIAtom> pseudo = do_GetAtom(buffer);
   if (!pseudo) {
     mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
     return eSelectorParsingStatus_Error;
   }
 
   // stash away some info about this pseudo so we only have to get it once.
   PRBool isTreePseudo = PR_FALSE;
@@ -3303,47 +3303,47 @@ CSSParserImpl::ParsePseudoClassWithNthPa
       for (PRUint32 i = mToken.mIdent.Length() - 1; i >= truncAt; --i) {
         mScanner.Pushback(mToken.mIdent[i]);
       }
       mToken.mIdent.Truncate(truncAt);
     }
   }
 
   if (eCSSToken_Ident == mToken.mType) {
-    if (mToken.mIdent.EqualsIgnoreCase("odd")) {
+    if (mToken.mIdent.LowerCaseEqualsLiteral("odd")) {
       numbers[0] = 2;
       numbers[1] = 1;
       lookForB = PR_FALSE;
     }
-    else if (mToken.mIdent.EqualsIgnoreCase("even")) {
+    else if (mToken.mIdent.LowerCaseEqualsLiteral("even")) {
       numbers[0] = 2;
       numbers[1] = 0;
       lookForB = PR_FALSE;
     }
-    else if (mToken.mIdent.EqualsIgnoreCase("n")) {
+    else if (mToken.mIdent.LowerCaseEqualsLiteral("n")) {
       numbers[0] = 1;
     }
-    else if (mToken.mIdent.EqualsIgnoreCase("-n")) {
+    else if (mToken.mIdent.LowerCaseEqualsLiteral("-n")) {
       numbers[0] = -1;
     }
     else {
       REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
       return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
     }
   }
   else if (eCSSToken_Number == mToken.mType) {
     if (!mToken.mIntegerValid) {
       REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
       return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
     }
     numbers[1] = mToken.mInteger;
     lookForB = PR_FALSE;
   }
   else if (eCSSToken_Dimension == mToken.mType) {
-    if (!mToken.mIntegerValid || !mToken.mIdent.EqualsIgnoreCase("n")) {
+    if (!mToken.mIntegerValid || !mToken.mIdent.LowerCaseEqualsLiteral("n")) {
       REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
       return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
     }
     numbers[0] = mToken.mInteger;
   }
   // XXX If it's a ')', is that valid?  (as 0n+0)
   else {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -142,17 +142,17 @@ struct RuleHashTagTableEntry : public Ru
 
 static PLDHashNumber
 RuleHash_CIHashKey(PLDHashTable *table, const void *key)
 {
   nsIAtom *atom = const_cast<nsIAtom*>(static_cast<const nsIAtom*>(key));
 
   nsAutoString str;
   atom->ToString(str);
-  ToUpperCase(str);
+  nsContentUtils::ASCIIToLower(str);
   return HashString(str);
 }
 
 typedef nsIAtom*
 (* RuleHashGetKey) (PLDHashTable *table, const PLDHashEntryHdr *entry);
 
 struct RuleHashTableOps {
   PLDHashTableOps ops;
@@ -1456,17 +1456,17 @@ static PRBool AttrMatchesValue(const nsA
   if (aAttrSelector->mValue.IsEmpty() &&
       (aAttrSelector->mFunction == NS_ATTR_FUNC_INCLUDES ||
        aAttrSelector->mFunction == NS_ATTR_FUNC_ENDSMATCH ||
        aAttrSelector->mFunction == NS_ATTR_FUNC_BEGINSMATCH ||
        aAttrSelector->mFunction == NS_ATTR_FUNC_CONTAINSMATCH))
     return PR_FALSE;
 
   const nsDefaultStringComparator defaultComparator;
-  const nsCaseInsensitiveStringComparator ciComparator;
+  const nsASCIICaseInsensitiveStringComparator ciComparator;
   const nsStringComparator& comparator =
       (aAttrSelector->mCaseSensitive || !isHTML)
                 ? static_cast<const nsStringComparator&>(defaultComparator)
                 : static_cast<const nsStringComparator&>(ciComparator);
 
   switch (aAttrSelector->mFunction) {
     case NS_ATTR_FUNC_EQUALS: 
       return aValue.Equals(aAttrSelector->mValue, comparator);
@@ -1757,17 +1757,17 @@ static PRBool SelectorMatches(RuleProces
         // We have to determine the language of the current element.  Since
         // this is currently no property and since the language is inherited
         // from the parent we have to be prepared to look at all parent
         // nodes.  The language itself is encoded in the LANG attribute.
         const nsString* lang = data.GetLang();
         if (lang && !lang->IsEmpty()) { // null check for out-of-memory
           if (!nsStyleUtil::DashMatchCompare(*lang,
                                              nsDependentString(pseudoClass->u.mString),
-                                             nsCaseInsensitiveStringComparator())) {
+                                             nsASCIICaseInsensitiveStringComparator())) {
             return PR_FALSE;
           }
           // This pseudo-class matched; move on to the next thing
           break;
         }
 
         nsIDocument* doc = data.mElement->GetDocument();
         if (doc) {
@@ -1785,17 +1785,17 @@ static PRBool SelectorMatches(RuleProces
           while (begin < len) {
             PRInt32 end = language.FindChar(PRUnichar(','), begin);
             if (end == kNotFound) {
               end = len;
             }
             if (nsStyleUtil::DashMatchCompare(Substring(language, begin,
                                                         end-begin),
                                               langString,
-                                              nsCaseInsensitiveStringComparator())) {
+                                              nsASCIICaseInsensitiveStringComparator())) {
               break;
             }
             begin = end + 1;
           }
           if (begin < len) {
             // This pseudo-class matched
             break;
           }
--- a/layout/style/nsCSSStyleRule.cpp
+++ b/layout/style/nsCSSStyleRule.cpp
@@ -235,17 +235,17 @@ nsAttrSelector::nsAttrSelector(PRInt32 a
     mCasedAttr(nsnull),
     mNameSpace(aNameSpace),
     mFunction(NS_ATTR_FUNC_SET),
     mCaseSensitive(1)
 {
   MOZ_COUNT_CTOR(nsAttrSelector);
 
   nsAutoString lowercase;
-  ToLowerCase(aAttr, lowercase);
+  nsContentUtils::ASCIIToLower(aAttr, lowercase);
   
   mCasedAttr = do_GetAtom(aAttr);
   mLowercaseAttr = do_GetAtom(lowercase);
 }
 
 nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunction, 
                                const nsString& aValue, PRBool aCaseSensitive)
   : mValue(aValue),
@@ -254,17 +254,17 @@ nsAttrSelector::nsAttrSelector(PRInt32 a
     mCasedAttr(nsnull),
     mNameSpace(aNameSpace),
     mFunction(aFunction),
     mCaseSensitive(aCaseSensitive)
 {
   MOZ_COUNT_CTOR(nsAttrSelector);
 
   nsAutoString lowercase;
-  ToLowerCase(aAttr, lowercase);
+  nsContentUtils::ASCIIToLower(aAttr, lowercase);
   
   mCasedAttr = do_GetAtom(aAttr);
   mLowercaseAttr = do_GetAtom(lowercase);
 }
 
 nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace,  nsIAtom* aLowercaseAttr,
                                nsIAtom* aCasedAttr, PRUint8 aFunction, 
                                const nsString& aValue, PRBool aCaseSensitive)
@@ -390,17 +390,17 @@ void nsCSSSelector::SetTag(const nsStrin
   if (aTag.IsEmpty()) {
     mLowercaseTag = mCasedTag =  nsnull;
     return;
   }
 
   mCasedTag = do_GetAtom(aTag);
  
   nsAutoString lowercase;
-  ToLowerCase(aTag, lowercase);
+  nsContentUtils::ASCIIToLower(aTag, lowercase);
   mLowercaseTag = do_GetAtom(lowercase);
 }
 
 void nsCSSSelector::AddID(const nsString& aID)
 {
   if (!aID.IsEmpty()) {
     nsAtomList** list = &mIDList;
     while (nsnull != *list) {
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -4564,17 +4564,17 @@ nsRuleNode::ComputeVisibilityData(void* 
     if (!gLangService) {
       CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService);
     }
 
     if (gLangService) {
       nsAutoString lang;
       displayData.mLang.GetStringValue(lang);
 
-      ToLowerCase(lang);
+      nsContentUtils::ASCIIToLower(lang);
       visibility->mLanguage = do_GetAtom(lang);
     }
   }
 
   COMPUTE_END_INHERITED(Visibility, visibility)
 }
 
 const void*