Bug 1370802: Make the lang rule operate on atoms, not strings. r?heycam
MozReview-Commit-ID: KG9i4Mc3ovN
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -151,17 +151,18 @@ GetDiscretelyAnimatedCSSValue(nsCSSPrope
NS_IMPL_ISUPPORTS(nsHTMLStyleSheet::LangRule, nsIStyleRule)
/* virtual */ void
nsHTMLStyleSheet::LangRule::MapRuleInfoInto(nsRuleData* aRuleData)
{
if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) {
nsCSSValue* lang = aRuleData->ValueForLang();
if (lang->GetUnit() == eCSSUnit_Null) {
- lang->SetStringValue(mLang, eCSSUnit_Ident);
+ nsCOMPtr<nsIAtom> langAtom = mLang;
+ lang->SetAtomIdentValue(langAtom.forget());
}
}
}
/* virtual */ bool
nsHTMLStyleSheet::LangRule::MightMapInheritedStyleData()
{
return true;
@@ -179,17 +180,17 @@ GetDiscretelyAnimatedCSSValue(nsCSSPrope
/* virtual */ void
nsHTMLStyleSheet::LangRule::List(FILE* out, int32_t aIndent) const
{
nsAutoCString str;
for (int32_t index = aIndent; --index >= 0; ) {
str.AppendLiteral(" ");
}
str.AppendLiteral("[lang rule] { language: \"");
- AppendUTF16toUTF8(mLang, str);
+ AppendUTF16toUTF8(nsDependentAtomString(mLang), str);
str.AppendLiteral("\" }\n");
fprintf_stderr(out, "%s", str.get());
}
#endif
// -----------------------------------------------------------
struct MappedAttrTableEntry : public PLDHashEntryHdr {
@@ -237,47 +238,47 @@ static const PLDHashTableOps MappedAttrT
struct LangRuleTableEntry : public PLDHashEntryHdr {
RefPtr<nsHTMLStyleSheet::LangRule> mRule;
};
static PLDHashNumber
LangRuleTable_HashKey(const void *key)
{
- const nsString *lang = static_cast<const nsString*>(key);
- return HashString(*lang);
+ auto* lang = static_cast<const nsIAtom*>(key);
+ return lang->hash();
}
static void
LangRuleTable_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
{
LangRuleTableEntry *entry = static_cast<LangRuleTableEntry*>(hdr);
entry->~LangRuleTableEntry();
memset(entry, 0, sizeof(LangRuleTableEntry));
}
static bool
LangRuleTable_MatchEntry(const PLDHashEntryHdr *hdr, const void *key)
{
- const nsString *lang = static_cast<const nsString*>(key);
+ auto* lang = static_cast<const nsIAtom*>(key);
const LangRuleTableEntry *entry = static_cast<const LangRuleTableEntry*>(hdr);
- return entry->mRule->mLang == *lang;
+ return entry->mRule->mLang == lang;
}
static void
LangRuleTable_InitEntry(PLDHashEntryHdr *hdr, const void *key)
{
- const nsString *lang = static_cast<const nsString*>(key);
+ auto* lang = static_cast<const nsIAtom*>(key);
- LangRuleTableEntry *entry = new (KnownNotNull, hdr) LangRuleTableEntry();
+ LangRuleTableEntry* entry = new (KnownNotNull, hdr) LangRuleTableEntry();
// Create the unique rule for this language
- entry->mRule = new nsHTMLStyleSheet::LangRule(*lang);
+ entry->mRule = new nsHTMLStyleSheet::LangRule(const_cast<nsIAtom*>(lang));
}
static const PLDHashTableOps LangRuleTable_Ops = {
LangRuleTable_HashKey,
LangRuleTable_MatchEntry,
PLDHashTable::MoveEntryStub,
LangRuleTable_ClearEntry,
LangRuleTable_InitEntry
@@ -345,26 +346,27 @@ nsHTMLStyleSheet::RulesMatching(ElementR
// considered style.
if (!ruleWalker->AuthorStyleDisabled() || aData->mElement->IsSVGElement()) {
aData->mElement->WalkContentStyleRules(ruleWalker);
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#language
// says that the xml:lang attribute overrides HTML's lang attribute,
// so we need to do this after WalkContentStyleRules.
- nsString lang;
- if (aData->mElement->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang, lang)) {
- ruleWalker->Forward(LangRuleFor(lang));
+ const nsAttrValue* langAttr =
+ aData->mElement->GetParsedAttr(nsGkAtoms::lang, kNameSpaceID_XML);
+ if (langAttr) {
+ MOZ_ASSERT(langAttr->Type() == nsAttrValue::eAtom);
+ ruleWalker->Forward(LangRuleFor(langAttr->GetAtomValue()));
}
// Set the language to "x-math" on the <math> element, so that appropriate
// font settings are used for MathML.
if (aData->mElement->IsMathMLElement(nsGkAtoms::math)) {
- nsGkAtoms::x_math->ToString(lang);
- ruleWalker->Forward(LangRuleFor(lang));
+ ruleWalker->Forward(LangRuleFor(nsGkAtoms::x_math));
}
}
// Test if style is dependent on content state
/* virtual */ nsRestyleHint
nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData)
{
if (aData->mElement->IsHTMLElement(nsGkAtoms::a) &&
@@ -584,20 +586,29 @@ nsHTMLStyleSheet::CalculateMappedServoDe
// Only handle cases which haven't been filled in already
continue;
}
attr->mAttributes->LazilyResolveServoDeclaration(aPresContext);
}
}
nsIStyleRule*
-nsHTMLStyleSheet::LangRuleFor(const nsString& aLanguage)
+nsHTMLStyleSheet::LangRuleFor(const nsIAtom* aLanguage)
{
+ Maybe<nsCOMPtr<nsIAtom>> lowerAtom;
+ nsDependentAtomString langString(aLanguage);
+ if (nsContentUtils::StringContainsASCIIUpper(langString)) {
+ nsString dest;
+ nsContentUtils::ASCIIToLower(langString, dest);
+ lowerAtom.emplace(NS_AtomizeMainThread(dest));
+ }
+
+ const nsIAtom* key = lowerAtom ? *lowerAtom : aLanguage;
auto entry =
- static_cast<LangRuleTableEntry*>(mLangRuleTable.Add(&aLanguage, fallible));
+ static_cast<LangRuleTableEntry*>(mLangRuleTable.Add(key, fallible));
if (!entry) {
NS_ASSERTION(false, "out of memory");
return nullptr;
}
return entry->mRule;
}
size_t
--- a/layout/style/nsHTMLStyleSheet.h
+++ b/layout/style/nsHTMLStyleSheet.h
@@ -9,16 +9,17 @@
* HTML attributes
*/
#ifndef nsHTMLStyleSheet_h_
#define nsHTMLStyleSheet_h_
#include "nsColor.h"
#include "nsCOMPtr.h"
+#include "nsIAtom.h"
#include "nsIStyleRule.h"
#include "nsIStyleRuleProcessor.h"
#include "PLDHashTable.h"
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
#include "nsString.h"
class nsIDocument;
@@ -73,19 +74,19 @@ public:
already_AddRefed<nsMappedAttributes>
UniqueMappedAttributes(nsMappedAttributes* aMapped);
void DropMappedAttributes(nsMappedAttributes* aMapped);
// For each mapped presentation attribute in the cache, resolve
// the attached ServoDeclarationBlock by running the mapping
// and converting the ruledata to Servo specified values.
void CalculateMappedServoDeclarations(nsPresContext* aPresContext);
- nsIStyleRule* LangRuleFor(const nsString& aLanguage);
+ nsIStyleRule* LangRuleFor(const nsIAtom* aLanguage);
-private:
+private:
nsHTMLStyleSheet(const nsHTMLStyleSheet& aCopy) = delete;
nsHTMLStyleSheet& operator=(const nsHTMLStyleSheet& aCopy) = delete;
~nsHTMLStyleSheet() {}
class HTMLColorRule;
friend class HTMLColorRule;
class HTMLColorRule final : public nsIStyleRule {
@@ -164,30 +165,30 @@ public: // for mLangRuleTable structures
// Rule to handle xml:lang attributes, of which we have exactly one
// per language string, maintained in mLangRuleTable.
// We also create one extra rule for the "x-math" language string, used on
// <math> elements.
class LangRule final : public nsIStyleRule {
private:
~LangRule() {}
public:
- explicit LangRule(const nsSubstring& aLang) : mLang(aLang) {}
+ explicit LangRule(nsIAtom* aLang) : mLang(aLang) {}
NS_DECL_ISUPPORTS
// nsIStyleRule interface
virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
virtual bool MightMapInheritedStyleData() override;
virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
nsCSSValue* aValue) override;
#ifdef DEBUG
virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
#endif
- nsString mLang;
+ nsCOMPtr<nsIAtom> mLang;
};
private:
nsIDocument* mDocument;
RefPtr<HTMLColorRule> mLinkRule;
RefPtr<HTMLColorRule> mVisitedRule;
RefPtr<HTMLColorRule> mActiveRule;
RefPtr<RawServoDeclarationBlock> mServoUnvisitedLinkDecl;