blob: 9c63e85371b345de1603a520ebbc22f25877b870 [file] [log] [blame]
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SKY_ENGINE_CORE_DOM_ELEMENTDATA_H_
#define SKY_ENGINE_CORE_DOM_ELEMENTDATA_H_
#include "sky/engine/core/dom/Attribute.h"
#include "sky/engine/core/dom/AttributeCollection.h"
#include "sky/engine/core/dom/SpaceSplitString.h"
#include "sky/engine/platform/heap/Handle.h"
#include "sky/engine/wtf/text/AtomicString.h"
namespace blink {
class ShareableElementData;
class StylePropertySet;
class UniqueElementData;
// ElementData represents very common, but not necessarily unique to an element,
// data such as attributes, inline style, and parsed class names and ids.
class ElementData : public RefCounted<ElementData> {
WTF_MAKE_FAST_ALLOCATED;
public:
// Override RefCounted's deref() to ensure operator delete is called on
// the appropriate subclass type.
void deref();
void clearClass() const { m_classNames.clear(); }
void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); }
const SpaceSplitString& classNames() const { return m_classNames; }
const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); }
AttributeCollection attributes() const;
bool hasID() const { return !m_idForStyleResolution.isNull(); }
bool hasClass() const { return !m_classNames.isNull(); }
bool isEquivalent(const ElementData* other) const;
bool isUnique() const { return m_isUnique; }
protected:
ElementData();
explicit ElementData(unsigned arraySize);
ElementData(const ElementData&, bool isUnique);
// Keep the type in a bitfield instead of using virtual destructors to avoid adding a vtable.
unsigned m_isUnique : 1;
unsigned m_arraySize : 28;
mutable unsigned m_styleAttributeIsDirty : 1;
mutable RefPtr<StylePropertySet> m_inlineStyle;
mutable SpaceSplitString m_classNames;
mutable AtomicString m_idForStyleResolution;
private:
friend class Element;
friend class ShareableElementData;
friend class UniqueElementData;
#if !ENABLE(OILPAN)
void destroy();
#endif
PassRefPtr<UniqueElementData> makeUniqueCopy() const;
};
#define DEFINE_ELEMENT_DATA_TYPE_CASTS(thisType, pointerPredicate, referencePredicate) \
template<typename T> inline thisType* to##thisType(const RefPtr<T>& data) { return to##thisType(data.get()); } \
DEFINE_TYPE_CASTS(thisType, ElementData, data, pointerPredicate, referencePredicate)
// SharableElementData is managed by ElementDataCache and is produced by
// the parser during page load for elements that have identical attributes. This
// is a memory optimization since it's very common for many elements to have
// duplicate sets of attributes (ex. the same classes).
class ShareableElementData final : public ElementData {
public:
static PassRefPtr<ShareableElementData> createWithAttributes(const Vector<Attribute>&);
explicit ShareableElementData(const Vector<Attribute>&);
explicit ShareableElementData(const UniqueElementData&);
~ShareableElementData();
// Add support for placement new as ShareableElementData is not allocated
// with a fixed size. Instead the allocated memory size is computed based on
// the number of attributes. This requires us to use Heap::allocate directly
// with the computed size and subsequently call placement new with the
// allocated memory address.
void* operator new(std::size_t, void* location)
{
return location;
}
AttributeCollection attributes() const;
Attribute m_attributeArray[0];
};
DEFINE_ELEMENT_DATA_TYPE_CASTS(ShareableElementData, !data->isUnique(), !data.isUnique());
// UniqueElementData is created when an element needs to mutate its attributes
// or gains presentation attribute style (ex. width="10"). It does not need to
// be created to fill in values in the ElementData that are derived from
// attributes. For example populating the m_inlineStyle from the style attribute
// doesn't require a UniqueElementData as all elements with the same style
// attribute will have the same inline style.
class UniqueElementData final : public ElementData {
public:
static PassRefPtr<UniqueElementData> create();
PassRefPtr<ShareableElementData> makeShareableCopy() const;
MutableAttributeCollection attributes();
AttributeCollection attributes() const;
UniqueElementData();
explicit UniqueElementData(const ShareableElementData&);
explicit UniqueElementData(const UniqueElementData&);
AttributeVector m_attributeVector;
};
DEFINE_ELEMENT_DATA_TYPE_CASTS(UniqueElementData, data->isUnique(), data.isUnique());
#if !ENABLE(OILPAN)
inline void ElementData::deref()
{
if (!derefBase())
return;
destroy();
}
#endif
inline AttributeCollection ElementData::attributes() const
{
if (isUnique())
return toUniqueElementData(this)->attributes();
return toShareableElementData(this)->attributes();
}
inline AttributeCollection ShareableElementData::attributes() const
{
return AttributeCollection(m_attributeArray, m_arraySize);
}
inline AttributeCollection UniqueElementData::attributes() const
{
return AttributeCollection(m_attributeVector.data(), m_attributeVector.size());
}
inline MutableAttributeCollection UniqueElementData::attributes()
{
return MutableAttributeCollection(m_attributeVector);
}
} // namespace blink
#endif // SKY_ENGINE_CORE_DOM_ELEMENTDATA_H_