Index: Source/core/css/CSSValue.h |
diff --git a/Source/core/css/CSSValue.h b/Source/core/css/CSSValue.h |
index 8ffa9dae64a3253b2e171beb2b767a161ff69b4b..a9c8ad8c73687498bba0ea91c67b92facaac1d3f 100644 |
--- a/Source/core/css/CSSValue.h |
+++ b/Source/core/css/CSSValue.h |
@@ -22,6 +22,7 @@ |
#define CSSValue_h |
#include "core/CoreExport.h" |
+#include "core/css/CSSPrimitiveValue.h" |
#include "core/css/CSSValueObject.h" |
#include "platform/heap/Handle.h" |
#include "wtf/RefCounted.h" |
@@ -40,6 +41,7 @@ public: |
: m_data(const_cast<CSSValueObject*>(&cssValueObject)) |
{ |
ASSERT(m_data); |
+ ASSERT(isObject()); |
ref(); |
} |
@@ -49,6 +51,7 @@ public: |
: m_data(cssValueObject.leakRef()) |
{ |
static_assert(WTF::IsSubclass<T, CSSValueObject>::value, "Parameter must be a container for CSSValueObject"); |
+ ASSERT(isObject()); |
ASSERT(m_data); |
} |
@@ -57,6 +60,7 @@ public: |
: m_data(cssValueObject.release().leakRef()) |
{ |
static_assert(WTF::IsSubclass<T, CSSValueObject>::value, "Parameter must be a container for CSSValueObject"); |
+ ASSERT(isObject()); |
ASSERT(m_data); |
} |
#endif |
@@ -67,6 +71,13 @@ public: |
ref(); |
} |
+ // Implicit conversion from CSSPrimitiveValue. |
+ CSSValue(const CSSPrimitiveValue& cssPrimitiveValue) |
+ : m_data(static_cast<CSSValueObject*>(cssPrimitiveValue.get())) |
+ { |
+ ref(); |
+ } |
+ |
~CSSValue() |
{ |
// Although m_data can't be null, a move constructor from NullableCSSValue |
@@ -92,18 +103,27 @@ public: |
} |
CSSValue(CSSValue&& rhs) |
+ : m_data(rhs.m_data) |
{ |
- m_data = rhs.m_data; |
+ rhs.m_data.clear(); |
} |
bool operator==(const CSSValue& other) const |
{ |
+ if (m_data == other.m_data) |
+ return true; |
+ if (!isObject() || !other.isObject()) |
+ return false; |
return m_data->equals(*other.m_data); |
} |
// TODO: Remove this and update callsites to use operator== instead. |
bool equals(const CSSValue& other) const |
{ |
+ if (m_data == other.m_data) |
+ return true; |
+ if (!isObject() || !other.isObject()) |
+ return false; |
return m_data->equals(*other.m_data); |
} |
@@ -113,46 +133,53 @@ public: |
} |
// Methods that proxy to CSSValueObject. |
- String cssText() const { return m_data->cssText(); } |
- bool hasFailedOrCanceledSubresources() const { return m_data->hasFailedOrCanceledSubresources(); }; |
- bool isPrimitiveValue() const { return m_data->isPrimitiveValue(); } |
- bool isValueList() const { return m_data->isValueList(); } |
- bool isBaseValueList() const { return m_data->isBaseValueList(); } |
- bool isBorderImageSliceValue() const { return m_data->isBorderImageSliceValue(); } |
- bool isCanvasValue() const { return m_data->isCanvasValue(); } |
- bool isCursorImageValue() const { return m_data->isCursorImageValue(); } |
- bool isCrossfadeValue() const { return m_data->isCrossfadeValue(); } |
- bool isFontFeatureValue() const { return m_data->isFontFeatureValue(); } |
- bool isFontFaceSrcValue() const { return m_data->isFontFaceSrcValue(); } |
- bool isFunctionValue() const { return m_data->isFunctionValue(); } |
- bool isImageGeneratorValue() const { return m_data->isImageGeneratorValue(); } |
- bool isGradientValue() const { return m_data->isGradientValue(); } |
- bool isImageSetValue() const { return m_data->isImageSetValue(); } |
- bool isImageValue() const { return m_data->isImageValue(); } |
- bool isImplicitInitialValue() const { return m_data->isImplicitInitialValue(); }; |
- bool isInheritedValue() const { return m_data->isInheritedValue(); }; |
- bool isInitialValue() const { return m_data->isInitialValue(); }; |
- bool isUnsetValue() const { return m_data->isUnsetValue(); }; |
- bool isCSSWideKeyword() const { return m_data->isCSSWideKeyword(); }; |
- bool isLinearGradientValue() const { return m_data->isLinearGradientValue(); }; |
- bool isPathValue() const { return m_data->isPathValue(); }; |
- bool isRadialGradientValue() const { return m_data->isRadialGradientValue(); }; |
- bool isReflectValue() const { return m_data->isReflectValue(); }; |
- bool isShadowValue() const { return m_data->isShadowValue(); }; |
- bool isCubicBezierTimingFunctionValue() const { return m_data->isCubicBezierTimingFunctionValue(); }; |
- bool isStepsTimingFunctionValue() const { return m_data->isStepsTimingFunctionValue(); }; |
- bool isLineBoxContainValue() const { return m_data->isLineBoxContainValue(); }; |
- bool isCalcValue() const { return m_data->isCalcValue(); }; |
- bool isGridTemplateAreasValue() const { return m_data->isGridTemplateAreasValue(); }; |
- bool isSVGDocumentValue() const { return m_data->isSVGDocumentValue(); }; |
- bool isContentDistributionValue() const { return m_data->isContentDistributionValue(); }; |
- bool isUnicodeRangeValue() const { return m_data->isUnicodeRangeValue(); }; |
- bool isGridLineNamesValue() const { return m_data->isGridLineNamesValue(); }; |
+ String cssText() const |
+ { |
+ if (isObject()) |
+ return m_data->cssText(); |
+ return CSSPrimitiveValue(reinterpret_cast<CSSPrimitiveValue::CSSLargePrimitiveValue*>(m_data.get())).cssText(); |
+ } |
+ |
+ bool hasFailedOrCanceledSubresources() const { return isObject() ? m_data->hasFailedOrCanceledSubresources() : false; }; |
+ bool isPrimitiveValue() const { return isObject() ? m_data->isPrimitiveValue() : true; } |
+ bool isValueList() const { return isObject() ? m_data->isValueList() : false; } |
+ bool isBaseValueList() const { return isObject() ? m_data->isBaseValueList() : false; } |
+ bool isBorderImageSliceValue() const { return isObject() ? m_data->isBorderImageSliceValue() : false; } |
+ bool isCanvasValue() const { return isObject() ? m_data->isCanvasValue() : false; } |
+ bool isCursorImageValue() const { return isObject() ? m_data->isCursorImageValue() : false; } |
+ bool isCrossfadeValue() const { return isObject() ? m_data->isCrossfadeValue() : false; } |
+ bool isFontFeatureValue() const { return isObject() ? m_data->isFontFeatureValue(): false; } |
+ bool isFontFaceSrcValue() const { return isObject() ? m_data->isFontFaceSrcValue(): false; } |
+ bool isFunctionValue() const { return isObject() ? m_data->isFunctionValue(): false; } |
+ bool isImageGeneratorValue() const { return isObject() ? m_data->isImageGeneratorValue(): false; } |
+ bool isGradientValue() const { return isObject() ? m_data->isGradientValue(): false; } |
+ bool isImageSetValue() const { return isObject() ? m_data->isImageSetValue(): false; } |
+ bool isImageValue() const { return isObject() ? m_data->isImageValue(): false; } |
+ bool isImplicitInitialValue() const { return isObject() ? m_data->isImplicitInitialValue(): false; } |
+ bool isInheritedValue() const { return isObject() ? m_data->isInheritedValue(): false; } |
+ bool isInitialValue() const { return isObject() ? m_data->isInitialValue(): false; } |
+ bool isUnsetValue() const { return isObject() ? m_data->isUnsetValue(): false; } |
+ bool isCSSWideKeyword() const { return isObject() ? m_data->isCSSWideKeyword(): false; } |
+ bool isLinearGradientValue() const { return isObject() ? m_data->isLinearGradientValue(): false; } |
+ bool isPathValue() const { return isObject() ? m_data->isPathValue(): false; } |
+ bool isRadialGradientValue() const { return isObject() ? m_data->isRadialGradientValue(): false; } |
+ bool isReflectValue() const { return isObject() ? m_data->isReflectValue(): false; } |
+ bool isShadowValue() const { return isObject() ? m_data->isShadowValue(): false; } |
+ bool isCubicBezierTimingFunctionValue() const { return isObject() ? m_data->isCubicBezierTimingFunctionValue(): false; } |
+ bool isStepsTimingFunctionValue() const { return isObject() ? m_data->isStepsTimingFunctionValue(): false; } |
+ bool isLineBoxContainValue() const { return isObject() ? m_data->isLineBoxContainValue(): false; } |
+ bool isCalcValue() const { return isObject() ? m_data->isCalcValue(): false; } |
+ bool isGridTemplateAreasValue() const { return isObject() ? m_data->isGridTemplateAreasValue(): false; } |
+ bool isSVGDocumentValue() const { return isObject() ? m_data->isSVGDocumentValue(): false; } |
+ bool isContentDistributionValue() const { return isObject() ? m_data->isContentDistributionValue(): false; } |
+ bool isUnicodeRangeValue() const { return isObject() ? m_data->isUnicodeRangeValue(): false; } |
+ bool isGridLineNamesValue() const { return isObject() ? m_data->isGridLineNamesValue(): false; } |
DEFINE_INLINE_TRACE() |
{ |
ASSERT(m_data); |
- visitor->trace(m_data); |
+ if (isObject()) |
+ visitor->trace(m_data); |
} |
// Only for use by the toFooCSSValue() macros. Don't use this. |
@@ -170,7 +197,7 @@ private: |
void ref() const |
{ |
#if !ENABLE(OILPAN) |
- if (m_data) |
+ if (m_data && isObject()) |
m_data->ref(); |
#endif |
} |
@@ -178,11 +205,16 @@ private: |
void deref() const |
{ |
#if !ENABLE(OILPAN) |
- if (m_data) |
+ if (m_data && isObject()) |
m_data->deref(); |
#endif |
} |
+ bool isObject() const |
+ { |
+ return !(*reinterpret_cast<const uintptr_t*>(&m_data) & 1); |
+ } |
+ |
RawPtrWillBeMember<CSSValueObject> m_data; |
}; |
@@ -238,18 +270,24 @@ public: |
} |
NullableCSSValue(NullableCSSValue&& rhs) |
+ : m_data(rhs.m_data) |
{ |
- m_data = rhs.m_data; |
- rhs.m_data = nullptr; |
+ rhs.m_data.clear(); |
} |
+ // Implicit conversion from CSSPrimitiveValue. |
+ NullableCSSValue(const CSSPrimitiveValue& cssPrimitiveValue) |
+ : m_data(static_cast<CSSValueObject*>(cssPrimitiveValue.get())) |
+ { |
+ ref(); |
+ } |
~NullableCSSValue() |
{ |
deref(); |
}; |
- operator bool() const |
+ explicit operator bool() const |
{ |
return m_data; |
} |
@@ -271,10 +309,14 @@ public: |
bool operator==(const NullableCSSValue& rhs) const |
{ |
+ if (m_data == rhs.m_data) |
+ return true; |
+ if (!isObject() || (rhs && !rhs.isObject())) |
+ return false; |
return m_data ? rhs.m_data && m_data->equals(*rhs.m_data) : !bool(rhs.m_data); |
} |
- bool operator!=(const NullableCSSValue& rhs) |
+ bool operator!=(const NullableCSSValue& rhs) const |
{ |
return !(*this == rhs); |
} |
@@ -311,7 +353,8 @@ public: |
DEFINE_INLINE_TRACE() |
{ |
- visitor->trace(m_data); |
+ if (isObject()) |
+ visitor->trace(m_data); |
} |
// Only for use by the toFooCSSValue() macros. Don't use this. |
@@ -326,7 +369,7 @@ private: |
void ref() const |
{ |
#if !ENABLE(OILPAN) |
- if (m_data) |
+ if (m_data && isObject()) |
m_data->ref(); |
#endif |
} |
@@ -334,17 +377,23 @@ private: |
void deref() const |
{ |
#if !ENABLE(OILPAN) |
- if (m_data) |
+ if (m_data && isObject()) |
m_data->deref(); |
#endif |
} |
+ bool isObject() const |
+ { |
+ return !(*reinterpret_cast<const uintptr_t*>(&m_data) & 1); |
+ } |
+ |
RawPtrWillBeMember<CSSValueObject> m_data; |
}; |
static_assert(sizeof(CSSValue) == sizeof(void*), "CSSValue should be pointer-sized"); |
static_assert(sizeof(NullableCSSValue) == sizeof(void*), "CSSValue should be pointer-sized"); |
static_assert(sizeof(CSSValue) == sizeof(NullableCSSValue), "Both CSSValue containers must contain the same data"); |
+static_assert(sizeof(CSSValue) == sizeof(CSSPrimitiveValue), "Both CSSValue and CSSPrimitiveValue must contain the same data"); |
template<size_t inlineCapacity> |
inline bool compareCSSValueVector(const WillBeHeapVector<CSSValue, inlineCapacity>& firstVector, const WillBeHeapVector<CSSValue, inlineCapacity>& secondVector) |
@@ -378,6 +427,24 @@ inline bool compareCSSValueVector(const WillBeHeapVector<CSSValue, inlineCapacit |
return static_cast<thisType*>(value.get()); \ |
} |
+inline const CSSPrimitiveValue& toCSSPrimitiveValue(const CSSValue& value) |
+{ |
+ ASSERT_WITH_SECURITY_IMPLICATION(value.isPrimitiveValue()); |
+ return *reinterpret_cast<const CSSPrimitiveValue*>(&value); |
+} |
+inline const CSSPrimitiveValue& toCSSPrimitiveValue(const NullableCSSValue& value) |
+{ |
+ ASSERT_WITH_SECURITY_IMPLICATION(value && value->isPrimitiveValue()); |
+ return *reinterpret_cast<const CSSPrimitiveValue*>(&value); |
+} |
+/* |
+inline CSSPrimitiveValue& toCSSPrimitiveValue(const CSSValue& value) |
+{ |
+ ASSERT_WITH_SECURITY_IMPLICATION(value.isPrimitiveValue()); |
+ return *const_cast<CSSPrimitiveValue*>(reinterpret_cast<const CSSPrimitiveValue*>(&value)); |
+} |
+*/ |
+ |
} // namespace blink |
WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(blink::CSSValue); |