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
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*