Commit 07a9d830 authored by fs's avatar fs Committed by Commit bot

Match <area shape> ASCII case-insensitively

The 'shape' attribute on HTMLAreaElement is an "enumerated attribute"
[1], which means that it should be matched ASCII case-insensitively[2].

To get a proper overload of equalIgnoringASCIICase(...) that matches the
required use (AtomicString against string literal/const char*),
restructure the definition of equalIgnoringASCIICase() to do away with
the templated version in favor of a generic StringImpl* version, and
specific wrappers around that one for AtomicString/String.
Also add a specialization for comparing against char/LChar.

No effect on the specified test because:
a) Invalid/missing value default is not per spec, so the unexpected shape
is picked anyway.
But more importantly:
b) the way case-folding is implemented/specified, no non-ASCII character
is case-folded to something in the ASCII-range.

[1] https://html.spec.whatwg.org/multipage/embedded-content.html#attr-area-shape
[2] https://html.spec.whatwg.org/multipage/infrastructure.html#enumerated-attribute

TEST=fast/html/area-shape.html
BUG=578125

Review URL: https://codereview.chromium.org/1624383002

Cr-Commit-Position: refs/heads/master@{#371478}
parent b4ffd219
......@@ -67,13 +67,13 @@ DEFINE_NODE_FACTORY(HTMLAreaElement)
void HTMLAreaElement::parseAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& value)
{
if (name == shapeAttr) {
if (equalIgnoringCase(value, "default"))
if (equalIgnoringASCIICase(value, "default"))
m_shape = Default;
else if (equalIgnoringCase(value, "circle"))
else if (equalIgnoringASCIICase(value, "circle"))
m_shape = Circle;
else if (equalIgnoringCase(value, "poly"))
else if (equalIgnoringASCIICase(value, "poly"))
m_shape = Poly;
else if (equalIgnoringCase(value, "rect"))
else if (equalIgnoringASCIICase(value, "rect"))
m_shape = Rect;
invalidateCachedRegion();
} else if (name == coordsAttr) {
......
......@@ -213,6 +213,9 @@ inline bool equalIgnoringCase(const LChar* a, const AtomicString& b) { return eq
inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); }
inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
inline bool equalIgnoringASCIICase(const AtomicString& a, const AtomicString& b) { return equalIgnoringASCIICase(a.impl(), b.impl()); }
inline bool equalIgnoringASCIICase(const AtomicString& a, const char* b) { return equalIgnoringASCIICase(a.impl(), reinterpret_cast<const LChar*>(b)); }
// Define external global variables for the commonly used atomic strings.
// These are only usable from the main thread.
WTF_EXPORT extern const AtomicString& nullAtom;
......
......@@ -2276,6 +2276,34 @@ bool equalIgnoringNullity(StringImpl* a, StringImpl* b)
return equal(a, b);
}
bool equalIgnoringASCIICase(const StringImpl* a, const StringImpl* b)
{
if (!a || !b)
return !a == !b;
unsigned length = b->length();
if (a->length() != length)
return false;
if (a->is8Bit()) {
if (b->is8Bit())
return equalIgnoringASCIICase(a->characters8(), b->characters8(), length);
return equalIgnoringASCIICase(a->characters8(), b->characters16(), length);
}
if (b->is8Bit())
return equalIgnoringASCIICase(a->characters16(), b->characters8(), length);
return equalIgnoringASCIICase(a->characters16(), b->characters16(), length);
}
bool equalIgnoringASCIICase(const StringImpl* a, const LChar* b)
{
if (!a || !b)
return !a == !b;
size_t length = strlen(reinterpret_cast<const char*>(b));
RELEASE_ASSERT(length <= numeric_limits<unsigned>::max());
if (length != a->length())
return false;
return equalSubstringIgnoringASCIICase(a, 0, b, length);
}
size_t StringImpl::sizeInBytes() const
{
size_t size = length();
......
......@@ -513,21 +513,8 @@ inline bool equalIgnoringASCIICase(const CharacterTypeA* a, const CharacterTypeB
return true;
}
template<typename CharacterTypeA, typename CharacterTypeB>
inline bool equalIgnoringASCIICase(const CharacterTypeA& a, const CharacterTypeB& b)
{
unsigned length = b.length();
if (a.length() != length)
return false;
if (a.is8Bit()) {
if (b.is8Bit())
return equalIgnoringASCIICase(a.characters8(), b.characters8(), length);
return equalIgnoringASCIICase(a.characters8(), b.characters16(), length);
}
if (b.is8Bit())
return equalIgnoringASCIICase(a.characters16(), b.characters8(), length);
return equalIgnoringASCIICase(a.characters16(), b.characters16(), length);
}
WTF_EXPORT bool equalIgnoringASCIICase(const StringImpl*, const StringImpl*);
WTF_EXPORT bool equalIgnoringASCIICase(const StringImpl*, const LChar*);
template<typename CharacterType>
inline size_t find(const CharacterType* characters, unsigned length, CharacterType matchCharacter, unsigned index = 0)
......
......@@ -502,6 +502,8 @@ inline bool equalIgnoringCase(const String& a, const char* b) { return equalIgno
inline bool equalIgnoringCase(const LChar* a, const String& b) { return equalIgnoringCase(a, b.impl()); }
inline bool equalIgnoringCase(const char* a, const String& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); }
inline bool equalIgnoringASCIICase(const String& a, const String& b) { return equalIgnoringASCIICase(a.impl(), b.impl()); }
inline bool equalPossiblyIgnoringCase(const String& a, const String& b, bool ignoreCase)
{
return ignoreCase ? equalIgnoringCase(a, b) : (a == b);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment