commit e4f1380f8cd0bb93ca1f3eacb4374748d8627a0c
parent 675ef662b1ec7d8cc28f1fc067faf31a74e5c91f
Author: Jonathan Kew <jkew@mozilla.com>
Date: Sat, 6 Dec 2025 00:21:51 +0000
Bug 2003721 - Canonicalize lang-subtag case during attribute mapping. r=layout-reviewers,emilio
Differential Revision: https://phabricator.services.mozilla.com/D275267
Diffstat:
1 file changed, 35 insertions(+), 3 deletions(-)
diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp
@@ -57,6 +57,7 @@
#include "mozilla/dom/ToggleEvent.h"
#include "mozilla/dom/TouchEvent.h"
#include "mozilla/dom/UnbindContext.h"
+#include "mozilla/intl/Locale.h"
#include "nsAtom.h"
#include "nsAttrValueOrString.h"
#include "nsCOMPtr.h"
@@ -1281,10 +1282,41 @@ static inline void MapLangAttributeInto(MappedDeclarationsBuilder& aBuilder) {
return;
}
MOZ_ASSERT(langValue->Type() == nsAttrValue::eAtom);
- aBuilder.SetIdentAtomValueIfUnset(eCSSProperty__x_lang,
- langValue->GetAtomValue());
+
+ // Adaptor for nsCString to expose the Buffer interface to Locale::ToString.
+ class BufferAdaptor {
+ public:
+ using CharType = char;
+
+ explicit BufferAdaptor(nsCString& aString) : mString(aString) {}
+ CharType* data() { return mString.BeginWriting(); }
+ size_t capacity() const { return mString.Length(); }
+ bool reserve(size_t aLen) { return mString.SetLength(aLen, fallible); }
+ void written(size_t aLen) { mString.SetLength(aLen); }
+
+ private:
+ nsCString& mString;
+ };
+
+ // Try parsing lang as a Locale and canonicalizing the subtags; if parsing
+ // succeeds, we record the canonicalized version rather than the original,
+ // so that code checking for particular codes can assume canonical casing.
+ // Note that in some cases this will also map 3-character ISO 639-3 tags to
+ // their corresponding 2-char ISO 639-1 tags.
+ RefPtr<nsAtom> lang = langValue->GetAtomValue();
+ nsAtomCString langStr(lang);
+ intl::Locale loc;
+ if (intl::LocaleParser::TryParse(langStr, loc).isOk() &&
+ loc.Canonicalize().isOk()) {
+ nsAutoCString canonical;
+ BufferAdaptor buffer(canonical);
+ if (loc.ToString(buffer).isOk() && canonical != langStr) {
+ lang = NS_Atomize(canonical);
+ }
+ }
+
+ aBuilder.SetIdentAtomValueIfUnset(eCSSProperty__x_lang, lang);
if (!aBuilder.PropertyIsSet(eCSSProperty_text_emphasis_position)) {
- const nsAtom* lang = langValue->GetAtomValue();
if (nsStyleUtil::MatchesLanguagePrefix(lang, u"zh")) {
aBuilder.SetKeywordValue(eCSSProperty_text_emphasis_position,
StyleTextEmphasisPosition::UNDER._0);