summaryrefslogtreecommitdiff
path: root/Source/WebCore/css/CSSSelector.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/css/CSSSelector.h')
-rw-r--r--Source/WebCore/css/CSSSelector.h559
1 files changed, 363 insertions, 196 deletions
diff --git a/Source/WebCore/css/CSSSelector.h b/Source/WebCore/css/CSSSelector.h
index 55ac62463..665a5f951 100644
--- a/Source/WebCore/css/CSSSelector.h
+++ b/Source/WebCore/css/CSSSelector.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
* 1999 Waldo Bastian (bastian@kde.org)
- * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2013, 2014 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -19,18 +19,21 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef CSSSelector_h
-#define CSSSelector_h
+#pragma once
#include "QualifiedName.h"
#include "RenderStyleConstants.h"
#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
namespace WebCore {
class CSSSelectorList;
+ enum class SelectorSpecificityIncrement {
+ ClassA = 0x10000,
+ ClassB = 0x100,
+ ClassC = 1
+ };
+
// this class represents a selector for a StyleRule
class CSSSelector {
WTF_MAKE_FAST_ALLOCATED;
@@ -44,14 +47,20 @@ namespace WebCore {
/**
* Re-create selector text from selector's data
*/
- String selectorText(const String& = "") const;
+ String selectorText(const String& = emptyString()) const;
// checks if the 2 selectors (including sub selectors) agree.
bool operator==(const CSSSelector&) const;
- // tag == -1 means apply to all elements (Selector = *)
+ static const unsigned maxValueMask = 0xffffff;
+ static const unsigned idMask = 0xff0000;
+ static const unsigned classMask = 0xff00;
+ static const unsigned elementMask = 0xff;
- unsigned specificity() const;
+ unsigned staticSpecificity(bool& ok) const;
+ unsigned specificityForPage() const;
+ unsigned simpleSelectorSpecificity() const;
+ static unsigned addSpecificities(unsigned, unsigned);
/* how the attribute value has to match.... Default is Exact */
enum Match {
@@ -71,101 +80,122 @@ namespace WebCore {
PagePseudoClass
};
- enum Relation {
- Descendant = 0,
+ enum RelationType {
+ Subselector,
+ DescendantSpace,
Child,
DirectAdjacent,
IndirectAdjacent,
- SubSelector,
- ShadowDescendant,
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ DescendantDoubleChild,
+#endif
+ ShadowDescendant
};
- enum PseudoType {
- PseudoNotParsed = 0,
- PseudoUnknown,
- PseudoEmpty,
- PseudoFirstChild,
- PseudoFirstOfType,
- PseudoLastChild,
- PseudoLastOfType,
- PseudoOnlyChild,
- PseudoOnlyOfType,
- PseudoFirstLine,
- PseudoFirstLetter,
- PseudoNthChild,
- PseudoNthOfType,
- PseudoNthLastChild,
- PseudoNthLastOfType,
- PseudoLink,
- PseudoVisited,
- PseudoAny,
- PseudoAnyLink,
- PseudoAutofill,
- PseudoHover,
- PseudoDrag,
- PseudoFocus,
- PseudoActive,
- PseudoChecked,
- PseudoEnabled,
- PseudoFullPageMedia,
- PseudoDefault,
- PseudoDisabled,
- PseudoOptional,
- PseudoRequired,
- PseudoReadOnly,
- PseudoReadWrite,
- PseudoValid,
- PseudoInvalid,
- PseudoIndeterminate,
- PseudoTarget,
- PseudoBefore,
- PseudoAfter,
- PseudoLang,
- PseudoNot,
- PseudoResizer,
- PseudoRoot,
- PseudoScope,
- PseudoScrollbar,
- PseudoScrollbarBack,
- PseudoScrollbarButton,
- PseudoScrollbarCorner,
- PseudoScrollbarForward,
- PseudoScrollbarThumb,
- PseudoScrollbarTrack,
- PseudoScrollbarTrackPiece,
- PseudoWindowInactive,
- PseudoCornerPresent,
- PseudoDecrement,
- PseudoIncrement,
- PseudoHorizontal,
- PseudoVertical,
- PseudoStart,
- PseudoEnd,
- PseudoDoubleButton,
- PseudoSingleButton,
- PseudoNoButton,
- PseudoSelection,
- PseudoLeftPage,
- PseudoRightPage,
- PseudoFirstPage,
+ enum PseudoClassType {
+ PseudoClassUnknown = 0,
+ PseudoClassEmpty,
+ PseudoClassFirstChild,
+ PseudoClassFirstOfType,
+ PseudoClassLastChild,
+ PseudoClassLastOfType,
+ PseudoClassOnlyChild,
+ PseudoClassOnlyOfType,
+ PseudoClassNthChild,
+ PseudoClassNthOfType,
+ PseudoClassNthLastChild,
+ PseudoClassNthLastOfType,
+ PseudoClassLink,
+ PseudoClassVisited,
+ PseudoClassAny,
+ PseudoClassAnyLink,
+ PseudoClassAnyLinkDeprecated,
+ PseudoClassAutofill,
+ PseudoClassHover,
+ PseudoClassDrag,
+ PseudoClassFocus,
+ PseudoClassFocusWithin,
+ PseudoClassActive,
+ PseudoClassChecked,
+ PseudoClassEnabled,
+ PseudoClassFullPageMedia,
+ PseudoClassDefault,
+ PseudoClassDisabled,
+ PseudoClassMatches,
+ PseudoClassOptional,
+ PseudoClassPlaceholderShown,
+ PseudoClassRequired,
+ PseudoClassReadOnly,
+ PseudoClassReadWrite,
+ PseudoClassValid,
+ PseudoClassInvalid,
+ PseudoClassIndeterminate,
+ PseudoClassTarget,
+ PseudoClassLang,
+ PseudoClassNot,
+ PseudoClassRoot,
+ PseudoClassScope,
+ PseudoClassWindowInactive,
+ PseudoClassCornerPresent,
+ PseudoClassDecrement,
+ PseudoClassIncrement,
+ PseudoClassHorizontal,
+ PseudoClassVertical,
+ PseudoClassStart,
+ PseudoClassEnd,
+ PseudoClassDoubleButton,
+ PseudoClassSingleButton,
+ PseudoClassNoButton,
#if ENABLE(FULLSCREEN_API)
- PseudoFullScreen,
- PseudoFullScreenDocument,
- PseudoFullScreenAncestor,
- PseudoAnimatingFullScreenTransition,
+ PseudoClassFullScreen,
+ PseudoClassFullScreenDocument,
+ PseudoClassFullScreenAncestor,
+ PseudoClassAnimatingFullScreenTransition,
#endif
- PseudoInRange,
- PseudoOutOfRange,
- PseudoUserAgentCustomElement,
- PseudoWebKitCustomElement,
+ PseudoClassInRange,
+ PseudoClassOutOfRange,
#if ENABLE(VIDEO_TRACK)
- PseudoCue,
- PseudoFutureCue,
- PseudoPastCue,
+ PseudoClassFuture,
+ PseudoClassPast,
#endif
-#if ENABLE(IFRAME_SEAMLESS)
- PseudoSeamlessDocument,
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ PseudoClassDir,
+ PseudoClassRole,
#endif
+ PseudoClassHost,
+ PseudoClassDefined,
+ };
+
+ enum PseudoElementType {
+ PseudoElementUnknown = 0,
+ PseudoElementAfter,
+ PseudoElementBefore,
+#if ENABLE(VIDEO_TRACK)
+ PseudoElementCue,
+#endif
+ PseudoElementFirstLetter,
+ PseudoElementFirstLine,
+ PseudoElementResizer,
+ PseudoElementScrollbar,
+ PseudoElementScrollbarButton,
+ PseudoElementScrollbarCorner,
+ PseudoElementScrollbarThumb,
+ PseudoElementScrollbarTrack,
+ PseudoElementScrollbarTrackPiece,
+ PseudoElementSelection,
+ PseudoElementSlotted,
+ PseudoElementUserAgentCustom,
+ PseudoElementWebKitCustom,
+
+ // WebKitCustom that appeared in an old prefixed form
+ // and need special handling.
+ PseudoElementWebKitCustomLegacyPrefixed,
+ };
+
+ enum PagePseudoClassType {
+ PagePseudoClassFirst = 1,
+ PagePseudoClassLeft,
+ PagePseudoClassRight,
};
enum MarginBoxType {
@@ -187,97 +217,181 @@ namespace WebCore {
RightBottomMarginBox,
};
- PseudoType pseudoType() const
- {
- if (m_pseudoType == PseudoNotParsed)
- extractPseudoType();
- return static_cast<PseudoType>(m_pseudoType);
- }
+ enum AttributeMatchType {
+ CaseSensitive,
+ CaseInsensitive,
+ };
- static PseudoType parsePseudoType(const AtomicString&);
- static PseudoId pseudoId(PseudoType);
+ static PseudoElementType parsePseudoElementType(const String&);
+ static PseudoId pseudoId(PseudoElementType);
// Selectors are kept in an array by CSSSelectorList. The next component of the selector is
// the next item in the array.
const CSSSelector* tagHistory() const { return m_isLastInTagHistory ? 0 : const_cast<CSSSelector*>(this + 1); }
const QualifiedName& tagQName() const;
+ const AtomicString& tagLowercaseLocalName() const;
+
const AtomicString& value() const;
+ const AtomicString& serializingValue() const;
const QualifiedName& attribute() const;
const AtomicString& attributeCanonicalLocalName() const;
const AtomicString& argument() const { return m_hasRareData ? m_data.m_rareData->m_argument : nullAtom; }
- const CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData->m_selectorList.get() : 0; }
+ bool attributeValueMatchingIsCaseInsensitive() const;
+ const Vector<AtomicString>* langArgumentList() const { return m_hasRareData ? m_data.m_rareData->m_langArgumentList.get() : nullptr; }
+ const CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData->m_selectorList.get() : nullptr; }
- void setValue(const AtomicString&);
- void setAttribute(const QualifiedName&, bool isCaseInsensitive);
+ void setValue(const AtomicString&, bool matchLowerCase = false);
+
+ // FIXME-NEWPARSER: These two methods can go away once the old parser is gone.
+ void setAttribute(const QualifiedName&, bool);
+ void setAttributeValueMatchingIsCaseInsensitive(bool);
+ void setAttribute(const QualifiedName&, bool convertToLowercase, AttributeMatchType);
+ void setNth(int a, int b);
void setArgument(const AtomicString&);
- void setSelectorList(PassOwnPtr<CSSSelectorList>);
+ void setLangArgumentList(std::unique_ptr<Vector<AtomicString>>);
+ void setSelectorList(std::unique_ptr<CSSSelectorList>);
bool parseNth() const;
bool matchNth(int count) const;
+ int nthA() const;
+ int nthB() const;
+
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ bool hasDescendantRelation() const { return relation() == DescendantSpace || relation() == DescendantDoubleChild; }
+#else
+ bool hasDescendantRelation() const { return relation() == DescendantSpace; }
+#endif
+
+ bool hasDescendantOrChildRelation() const { return relation() == Child || hasDescendantRelation(); }
+
+ PseudoClassType pseudoClassType() const
+ {
+ ASSERT(match() == PseudoClass);
+ return static_cast<PseudoClassType>(m_pseudoType);
+ }
+ void setPseudoClassType(PseudoClassType pseudoType)
+ {
+ m_pseudoType = pseudoType;
+ ASSERT(m_pseudoType == pseudoType);
+ }
+
+ PseudoElementType pseudoElementType() const
+ {
+ ASSERT(match() == PseudoElement);
+ return static_cast<PseudoElementType>(m_pseudoType);
+ }
+ void setPseudoElementType(PseudoElementType pseudoElementType)
+ {
+ m_pseudoType = pseudoElementType;
+ ASSERT(m_pseudoType == pseudoElementType);
+ }
+
+ PagePseudoClassType pagePseudoClassType() const
+ {
+ ASSERT(match() == PagePseudoClass);
+ return static_cast<PagePseudoClassType>(m_pseudoType);
+ }
+ void setPagePseudoType(PagePseudoClassType pagePseudoType)
+ {
+ m_pseudoType = pagePseudoType;
+ ASSERT(m_pseudoType == pagePseudoType);
+ }
bool matchesPseudoElement() const;
bool isUnknownPseudoElement() const;
bool isCustomPseudoElement() const;
+ bool isWebKitCustomPseudoElement() const;
bool isSiblingSelector() const;
bool isAttributeSelector() const;
- Relation relation() const { return static_cast<Relation>(m_relation); }
+ RelationType relation() const { return static_cast<RelationType>(m_relation); }
+ void setRelation(RelationType relation)
+ {
+ m_relation = relation;
+ ASSERT(m_relation == relation);
+ }
+
+ Match match() const { return static_cast<Match>(m_match); }
+ void setMatch(Match match)
+ {
+ m_match = match;
+ ASSERT(m_match == match);
+ }
bool isLastInSelectorList() const { return m_isLastInSelectorList; }
void setLastInSelectorList() { m_isLastInSelectorList = true; }
bool isLastInTagHistory() const { return m_isLastInTagHistory; }
void setNotLastInTagHistory() { m_isLastInTagHistory = false; }
- bool isSimple() const;
-
bool isForPage() const { return m_isForPage; }
void setForPage() { m_isForPage = true; }
- unsigned m_relation : 3; // enum Relation
- mutable unsigned m_match : 4; // enum Match
- mutable unsigned m_pseudoType : 8; // PseudoType
-
private:
- mutable bool m_parsedNth : 1; // Used for :nth-*
- bool m_isLastInSelectorList : 1;
- bool m_isLastInTagHistory : 1;
- bool m_hasRareData : 1;
- bool m_isForPage : 1;
- bool m_tagIsForNamespaceRule : 1;
-
- unsigned specificityForOneSelector() const;
- unsigned specificityForPage() const;
- void extractPseudoType() const;
+ unsigned m_relation : 4; // enum RelationType.
+ mutable unsigned m_match : 4; // enum Match.
+ mutable unsigned m_pseudoType : 8; // PseudoType.
+ mutable unsigned m_parsedNth : 1; // Used for :nth-*.
+ unsigned m_isLastInSelectorList : 1;
+ unsigned m_isLastInTagHistory : 1;
+ unsigned m_hasRareData : 1;
+ unsigned m_hasNameWithCase : 1;
+ unsigned m_isForPage : 1;
+ unsigned m_tagIsForNamespaceRule : 1;
+ unsigned m_caseInsensitiveAttributeValueMatching : 1;
+#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
+ unsigned m_destructorHasBeenCalled : 1;
+#endif
+
+ unsigned simpleSelectorSpecificityForPage() const;
// Hide.
CSSSelector& operator=(const CSSSelector&);
struct RareData : public RefCounted<RareData> {
- static PassRefPtr<RareData> create(PassRefPtr<AtomicStringImpl> value) { return adoptRef(new RareData(value)); }
+ static Ref<RareData> create(AtomicString&& value) { return adoptRef(*new RareData(WTFMove(value))); }
~RareData();
bool parseNth();
bool matchNth(int count);
- AtomicStringImpl* m_value; // Plain pointer to keep things uniform with the union.
+ // For quirks mode, class and id are case-insensitive. In the case where uppercase
+ // letters are used in quirks mode, |m_matchingValue| holds the lowercase class/id
+ // and |m_serializingValue| holds the original string.
+ AtomicString m_matchingValue;
+ AtomicString m_serializingValue;
+
int m_a; // Used for :nth-*
int m_b; // Used for :nth-*
QualifiedName m_attribute; // used for attribute selector
AtomicString m_attributeCanonicalLocalName;
- AtomicString m_argument; // Used for :contains, :lang and :nth-*
- OwnPtr<CSSSelectorList> m_selectorList; // Used for :-webkit-any and :not
+ AtomicString m_argument; // Used for :contains and :nth-*
+ std::unique_ptr<Vector<AtomicString>> m_langArgumentList; // Used for :lang arguments.
+ std::unique_ptr<CSSSelectorList> m_selectorList; // Used for :matches() and :not().
private:
- RareData(PassRefPtr<AtomicStringImpl> value);
+ RareData(AtomicString&& value);
};
void createRareData();
+ struct NameWithCase : public RefCounted<NameWithCase> {
+ NameWithCase(const QualifiedName& originalName, const AtomicString& lowercaseName)
+ : m_originalName(originalName)
+ , m_lowercaseLocalName(lowercaseName)
+ {
+ ASSERT(originalName.localName() != lowercaseName);
+ }
+
+ const QualifiedName m_originalName;
+ const AtomicString m_lowercaseLocalName;
+ };
+
union DataUnion {
DataUnion() : m_value(0) { }
AtomicStringImpl* m_value;
QualifiedName::QualifiedNameImpl* m_tagQName;
RareData* m_rareData;
+ NameWithCase* m_nameWithCase;
} m_data;
};
@@ -297,96 +411,98 @@ inline const AtomicString& CSSSelector::attributeCanonicalLocalName() const
inline bool CSSSelector::matchesPseudoElement() const
{
- if (m_pseudoType == PseudoUnknown)
- extractPseudoType();
- return m_match == PseudoElement;
+ return match() == PseudoElement;
}
inline bool CSSSelector::isUnknownPseudoElement() const
{
- return m_match == PseudoElement && m_pseudoType == PseudoUnknown;
+ return match() == PseudoElement && pseudoElementType() == PseudoElementUnknown;
}
inline bool CSSSelector::isCustomPseudoElement() const
{
- return m_match == PseudoElement && (m_pseudoType == PseudoUserAgentCustomElement || m_pseudoType == PseudoWebKitCustomElement);
+ return match() == PseudoElement
+ && (pseudoElementType() == PseudoElementUserAgentCustom
+ || pseudoElementType() == PseudoElementWebKitCustom
+ || pseudoElementType() == PseudoElementWebKitCustomLegacyPrefixed);
+}
+
+inline bool CSSSelector::isWebKitCustomPseudoElement() const
+{
+ return pseudoElementType() == PseudoElementWebKitCustom || pseudoElementType() == PseudoElementWebKitCustomLegacyPrefixed;
+}
+
+static inline bool pseudoClassIsRelativeToSiblings(CSSSelector::PseudoClassType type)
+{
+ return type == CSSSelector::PseudoClassEmpty
+ || type == CSSSelector::PseudoClassFirstChild
+ || type == CSSSelector::PseudoClassFirstOfType
+ || type == CSSSelector::PseudoClassLastChild
+ || type == CSSSelector::PseudoClassLastOfType
+ || type == CSSSelector::PseudoClassOnlyChild
+ || type == CSSSelector::PseudoClassOnlyOfType
+ || type == CSSSelector::PseudoClassNthChild
+ || type == CSSSelector::PseudoClassNthOfType
+ || type == CSSSelector::PseudoClassNthLastChild
+ || type == CSSSelector::PseudoClassNthLastOfType;
}
inline bool CSSSelector::isSiblingSelector() const
{
- PseudoType type = pseudoType();
- return m_relation == DirectAdjacent
- || m_relation == IndirectAdjacent
- || type == PseudoEmpty
- || type == PseudoFirstChild
- || type == PseudoFirstOfType
- || type == PseudoLastChild
- || type == PseudoLastOfType
- || type == PseudoOnlyChild
- || type == PseudoOnlyOfType
- || type == PseudoNthChild
- || type == PseudoNthOfType
- || type == PseudoNthLastChild
- || type == PseudoNthLastOfType;
+ return relation() == DirectAdjacent
+ || relation() == IndirectAdjacent
+ || (match() == CSSSelector::PseudoClass && pseudoClassIsRelativeToSiblings(pseudoClassType()));
}
inline bool CSSSelector::isAttributeSelector() const
{
- return m_match == CSSSelector::Exact
- || m_match == CSSSelector::Set
- || m_match == CSSSelector::List
- || m_match == CSSSelector::Hyphen
- || m_match == CSSSelector::Contain
- || m_match == CSSSelector::Begin
- || m_match == CSSSelector::End;
+ return match() == CSSSelector::Exact
+ || match() == CSSSelector::Set
+ || match() == CSSSelector::List
+ || match() == CSSSelector::Hyphen
+ || match() == CSSSelector::Contain
+ || match() == CSSSelector::Begin
+ || match() == CSSSelector::End;
}
-inline void CSSSelector::setValue(const AtomicString& value)
+inline void CSSSelector::setValue(const AtomicString& value, bool matchLowerCase)
{
- ASSERT(m_match != Tag);
- ASSERT(m_pseudoType == PseudoNotParsed);
+ ASSERT(match() != Tag);
+ AtomicString matchingValue = matchLowerCase ? value.convertToASCIILowercase() : value;
+ if (!m_hasRareData && matchingValue != value)
+ createRareData();
+
// Need to do ref counting manually for the union.
- if (m_hasRareData) {
- if (m_data.m_rareData->m_value)
- m_data.m_rareData->m_value->deref();
- m_data.m_rareData->m_value = value.impl();
- m_data.m_rareData->m_value->ref();
+ if (!m_hasRareData) {
+ if (m_data.m_value)
+ m_data.m_value->deref();
+ m_data.m_value = value.impl();
+ m_data.m_value->ref();
return;
}
- if (m_data.m_value)
- m_data.m_value->deref();
- m_data.m_value = value.impl();
- m_data.m_value->ref();
+
+ m_data.m_rareData->m_matchingValue = WTFMove(matchingValue);
+ m_data.m_rareData->m_serializingValue = value;
}
inline CSSSelector::CSSSelector()
- : m_relation(Descendant)
+ : m_relation(DescendantSpace)
, m_match(Unknown)
- , m_pseudoType(PseudoNotParsed)
+ , m_pseudoType(0)
, m_parsedNth(false)
, m_isLastInSelectorList(false)
, m_isLastInTagHistory(true)
, m_hasRareData(false)
+ , m_hasNameWithCase(false)
, m_isForPage(false)
, m_tagIsForNamespaceRule(false)
+ , m_caseInsensitiveAttributeValueMatching(false)
+#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
+ , m_destructorHasBeenCalled(false)
+#endif
{
}
-inline CSSSelector::CSSSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule)
- : m_relation(Descendant)
- , m_match(Tag)
- , m_pseudoType(PseudoNotParsed)
- , m_parsedNth(false)
- , m_isLastInSelectorList(false)
- , m_isLastInTagHistory(true)
- , m_hasRareData(false)
- , m_isForPage(false)
- , m_tagIsForNamespaceRule(tagIsForNamespaceRule)
-{
- m_data.m_tagQName = tagQName.impl();
- m_data.m_tagQName->ref();
-}
-
inline CSSSelector::CSSSelector(const CSSSelector& o)
: m_relation(o.m_relation)
, m_match(o.m_match)
@@ -395,15 +511,23 @@ inline CSSSelector::CSSSelector(const CSSSelector& o)
, m_isLastInSelectorList(o.m_isLastInSelectorList)
, m_isLastInTagHistory(o.m_isLastInTagHistory)
, m_hasRareData(o.m_hasRareData)
+ , m_hasNameWithCase(o.m_hasNameWithCase)
, m_isForPage(o.m_isForPage)
, m_tagIsForNamespaceRule(o.m_tagIsForNamespaceRule)
+ , m_caseInsensitiveAttributeValueMatching(o.m_caseInsensitiveAttributeValueMatching)
+#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
+ , m_destructorHasBeenCalled(false)
+#endif
{
- if (o.m_match == Tag) {
- m_data.m_tagQName = o.m_data.m_tagQName;
- m_data.m_tagQName->ref();
- } else if (o.m_hasRareData) {
+ if (o.m_hasRareData) {
m_data.m_rareData = o.m_data.m_rareData;
m_data.m_rareData->ref();
+ } else if (o.m_hasNameWithCase) {
+ m_data.m_nameWithCase = o.m_data.m_nameWithCase;
+ m_data.m_nameWithCase->ref();
+ } if (o.match() == Tag) {
+ m_data.m_tagQName = o.m_data.m_tagQName;
+ m_data.m_tagQName->ref();
} else if (o.m_data.m_value) {
m_data.m_value = o.m_data.m_value;
m_data.m_value->ref();
@@ -412,29 +536,72 @@ inline CSSSelector::CSSSelector(const CSSSelector& o)
inline CSSSelector::~CSSSelector()
{
- if (m_match == Tag)
- m_data.m_tagQName->deref();
- else if (m_hasRareData)
+ ASSERT_WITH_SECURITY_IMPLICATION(!m_destructorHasBeenCalled);
+#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
+ m_destructorHasBeenCalled = true;
+#endif
+ if (m_hasRareData) {
m_data.m_rareData->deref();
- else if (m_data.m_value)
+ m_data.m_rareData = nullptr;
+ m_hasRareData = false;
+ } else if (m_hasNameWithCase) {
+ m_data.m_nameWithCase->deref();
+ m_data.m_nameWithCase = nullptr;
+ m_hasNameWithCase = false;
+ } else if (match() == Tag) {
+ m_data.m_tagQName->deref();
+ m_data.m_tagQName = nullptr;
+ m_match = Unknown;
+ } else if (m_data.m_value) {
m_data.m_value->deref();
+ m_data.m_value = nullptr;
+ }
}
inline const QualifiedName& CSSSelector::tagQName() const
{
- ASSERT(m_match == Tag);
+ ASSERT(match() == Tag);
+ if (m_hasNameWithCase)
+ return m_data.m_nameWithCase->m_originalName;
return *reinterpret_cast<const QualifiedName*>(&m_data.m_tagQName);
}
+inline const AtomicString& CSSSelector::tagLowercaseLocalName() const
+{
+ if (m_hasNameWithCase)
+ return m_data.m_nameWithCase->m_lowercaseLocalName;
+ return m_data.m_tagQName->m_localName;
+}
+
inline const AtomicString& CSSSelector::value() const
{
- ASSERT(m_match != Tag);
+ ASSERT(match() != Tag);
+ if (m_hasRareData)
+ return m_data.m_rareData->m_matchingValue;
+
// AtomicString is really just an AtomicStringImpl* so the cast below is safe.
- // FIXME: Perhaps call sites could be changed to accept AtomicStringImpl?
- return *reinterpret_cast<const AtomicString*>(m_hasRareData ? &m_data.m_rareData->m_value : &m_data.m_value);
+ return *reinterpret_cast<const AtomicString*>(&m_data.m_value);
}
+inline const AtomicString& CSSSelector::serializingValue() const
+{
+ ASSERT(match() != Tag);
+ if (m_hasRareData)
+ return m_data.m_rareData->m_serializingValue;
+
+ // AtomicString is really just an AtomicStringImpl* so the cast below is safe.
+ return *reinterpret_cast<const AtomicString*>(&m_data.m_value);
+}
-} // namespace WebCore
+inline void CSSSelector::setAttributeValueMatchingIsCaseInsensitive(bool isCaseInsensitive)
+{
+ ASSERT(isAttributeSelector() && match() != CSSSelector::Set);
+ m_caseInsensitiveAttributeValueMatching = isCaseInsensitive;
+}
+
+inline bool CSSSelector::attributeValueMatchingIsCaseInsensitive() const
+{
+ return m_caseInsensitiveAttributeValueMatching;
+}
-#endif // CSSSelector_h
+} // namespace WebCore