Bug 1839223 - Remove nsMappedAttributes. r=smaug

Instead, lazily schedule evaluation of them before styling, much like we
were doing for SVG.

A subtle tweak is that we only remain scheduled while in the document.
This allows us to use the "in document" bit plus the "mapped attributes
dirty" bit to know our scheduled status. It also prevents doing silly
work for disconnected elements, and having to do hashmap lookups on
adoption and node destruction.

Differential Revision: https://phabricator.services.mozilla.com/D181549
This commit is contained in:
Emilio Cobos Álvarez 2023-06-22 17:22:03 +00:00
parent 4bba5ff713
commit 7bddcf9e5a
97 changed files with 1132 additions and 2193 deletions

View File

@ -15,40 +15,47 @@
#include "mozilla/CheckedInt.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/dom/Document.h"
#include "mozilla/ServoBindings.h"
#include "nsMappedAttributeElement.h"
#include "nsString.h"
#include "nsMappedAttributes.h"
#include "nsUnicharUtils.h"
#include "nsContentUtils.h" // nsAutoScriptBlocker
using mozilla::CheckedUint32;
using mozilla::dom::Document;
AttrArray::Impl::~Impl() {
for (InternalAttr& attr : NonMappedAttrs()) {
for (InternalAttr& attr : Attrs()) {
attr.~InternalAttr();
}
if (auto* decl = GetMappedDeclarationBlock()) {
Servo_DeclarationBlock_Release(decl);
mMappedAttributeBits = 0;
}
}
NS_IF_RELEASE(mMappedAttrs);
void AttrArray::SetMappedDeclarationBlock(
already_AddRefed<mozilla::StyleLockedDeclarationBlock> aBlock) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mImpl);
MOZ_ASSERT(IsPendingMappedAttributeEvaluation());
if (auto* decl = GetMappedDeclarationBlock()) {
Servo_DeclarationBlock_Release(decl);
}
mImpl->mMappedAttributeBits = reinterpret_cast<uintptr_t>(aBlock.take());
MOZ_ASSERT(!IsPendingMappedAttributeEvaluation());
}
const nsAttrValue* AttrArray::GetAttr(const nsAtom* aLocalName,
int32_t aNamespaceID) const {
if (aNamespaceID == kNameSpaceID_None) {
// This should be the common case so lets make an optimized loop
for (const InternalAttr& attr : NonMappedAttrs()) {
for (const InternalAttr& attr : Attrs()) {
if (attr.mName.Equals(aLocalName)) {
return &attr.mValue;
}
}
if (mImpl && mImpl->mMappedAttrs) {
return mImpl->mMappedAttrs->GetAttr(aLocalName);
}
} else {
for (const InternalAttr& attr : NonMappedAttrs()) {
for (const InternalAttr& attr : Attrs()) {
if (attr.mName.Equals(aLocalName, aNamespaceID)) {
return &attr.mValue;
}
@ -59,16 +66,11 @@ const nsAttrValue* AttrArray::GetAttr(const nsAtom* aLocalName,
}
const nsAttrValue* AttrArray::GetAttr(const nsAString& aLocalName) const {
for (const InternalAttr& attr : NonMappedAttrs()) {
for (const InternalAttr& attr : Attrs()) {
if (attr.mName.Equals(aLocalName)) {
return &attr.mValue;
}
}
if (mImpl && mImpl->mMappedAttrs) {
return mImpl->mMappedAttrs->GetAttr(aLocalName);
}
return nullptr;
}
@ -85,28 +87,18 @@ const nsAttrValue* AttrArray::GetAttr(const nsAString& aName,
return GetAttr(lowercase, eCaseMatters);
}
for (const InternalAttr& attr : NonMappedAttrs()) {
for (const InternalAttr& attr : Attrs()) {
if (attr.mName.QualifiedNameEquals(aName)) {
return &attr.mValue;
}
}
if (mImpl && mImpl->mMappedAttrs) {
return mImpl->mMappedAttrs->GetAttr(aName);
}
return nullptr;
}
const nsAttrValue* AttrArray::AttrAt(uint32_t aPos) const {
NS_ASSERTION(aPos < AttrCount(), "out-of-bounds access in AttrArray");
uint32_t nonmapped = NonMappedAttrCount();
if (aPos < nonmapped) {
return &mImpl->NonMappedAttrs()[aPos].mValue;
}
return mImpl->mMappedAttrs->AttrAt(aPos - nonmapped);
return &mImpl->Attrs()[aPos].mValue;
}
template <typename Name>
@ -129,7 +121,7 @@ nsresult AttrArray::SetAndSwapAttr(nsAtom* aLocalName, nsAttrValue& aValue,
bool* aHadValue) {
*aHadValue = false;
for (InternalAttr& attr : NonMappedAttrs()) {
for (InternalAttr& attr : Attrs()) {
if (attr.mName.Equals(aLocalName)) {
attr.mValue.SwapValueWith(aValue);
*aHadValue = true;
@ -149,7 +141,7 @@ nsresult AttrArray::SetAndSwapAttr(mozilla::dom::NodeInfo* aName,
}
*aHadValue = false;
for (InternalAttr& attr : NonMappedAttrs()) {
for (InternalAttr& attr : Attrs()) {
if (attr.mName.Equals(localName, namespaceID)) {
attr.mName.SetTo(aName);
attr.mValue.SwapValueWith(aValue);
@ -164,82 +156,41 @@ nsresult AttrArray::SetAndSwapAttr(mozilla::dom::NodeInfo* aName,
nsresult AttrArray::RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue) {
NS_ASSERTION(aPos < AttrCount(), "out-of-bounds");
uint32_t nonmapped = NonMappedAttrCount();
if (aPos < nonmapped) {
mImpl->mBuffer[aPos].mValue.SwapValueWith(aValue);
mImpl->mBuffer[aPos].~InternalAttr();
mImpl->mBuffer[aPos].mValue.SwapValueWith(aValue);
mImpl->mBuffer[aPos].~InternalAttr();
memmove(mImpl->mBuffer + aPos, mImpl->mBuffer + aPos + 1,
(mImpl->mAttrCount - aPos - 1) * sizeof(InternalAttr));
memmove(mImpl->mBuffer + aPos, mImpl->mBuffer + aPos + 1,
(mImpl->mAttrCount - aPos - 1) * sizeof(InternalAttr));
--mImpl->mAttrCount;
return NS_OK;
}
if (MappedAttrCount() == 1) {
// We're removing the last mapped attribute. Can't swap in this
// case; have to copy.
aValue.SetTo(*mImpl->mMappedAttrs->AttrAt(0));
NS_RELEASE(mImpl->mMappedAttrs);
return NS_OK;
}
RefPtr<nsMappedAttributes> mapped = ModifiableMapped(nullptr, false);
mapped->RemoveAttrAt(aPos - nonmapped, aValue);
return MakeMappedUnique(mapped);
--mImpl->mAttrCount;
return NS_OK;
}
mozilla::dom::BorrowedAttrInfo AttrArray::AttrInfoAt(uint32_t aPos) const {
NS_ASSERTION(aPos < AttrCount(), "out-of-bounds access in AttrArray");
uint32_t nonmapped = NonMappedAttrCount();
if (aPos < nonmapped) {
InternalAttr& attr = mImpl->mBuffer[aPos];
return BorrowedAttrInfo(&attr.mName, &attr.mValue);
}
return BorrowedAttrInfo(mImpl->mMappedAttrs->NameAt(aPos - nonmapped),
mImpl->mMappedAttrs->AttrAt(aPos - nonmapped));
InternalAttr& attr = mImpl->mBuffer[aPos];
return BorrowedAttrInfo(&attr.mName, &attr.mValue);
}
const nsAttrName* AttrArray::AttrNameAt(uint32_t aPos) const {
NS_ASSERTION(aPos < AttrCount(), "out-of-bounds access in AttrArray");
uint32_t nonmapped = NonMappedAttrCount();
if (aPos < nonmapped) {
return &mImpl->mBuffer[aPos].mName;
}
return mImpl->mMappedAttrs->NameAt(aPos - nonmapped);
return &mImpl->mBuffer[aPos].mName;
}
const nsAttrName* AttrArray::GetSafeAttrNameAt(uint32_t aPos) const {
uint32_t nonmapped = NonMappedAttrCount();
if (aPos < nonmapped) {
return &mImpl->mBuffer[aPos].mName;
}
if (aPos >= AttrCount()) {
return nullptr;
}
return mImpl->mMappedAttrs->NameAt(aPos - nonmapped);
return &mImpl->mBuffer[aPos].mName;
}
const nsAttrName* AttrArray::GetExistingAttrNameFromQName(
const nsAString& aName) const {
for (const InternalAttr& attr : NonMappedAttrs()) {
for (const InternalAttr& attr : Attrs()) {
if (attr.mName.QualifiedNameEquals(aName)) {
return &attr.mName;
}
}
if (mImpl && mImpl->mMappedAttrs) {
return mImpl->mMappedAttrs->GetExistingAttrNameFromQName(aName);
}
return nullptr;
}
@ -249,14 +200,6 @@ int32_t AttrArray::IndexOfAttr(const nsAtom* aLocalName,
return -1;
}
int32_t idx;
if (mImpl->mMappedAttrs && aNamespaceID == kNameSpaceID_None) {
idx = mImpl->mMappedAttrs->IndexOfAttr(aLocalName);
if (idx >= 0) {
return NonMappedAttrCount() + idx;
}
}
uint32_t i = 0;
if (aNamespaceID == kNameSpaceID_None) {
// This should be the common case so lets make an optimized loop
@ -265,14 +208,14 @@ int32_t AttrArray::IndexOfAttr(const nsAtom* aLocalName,
// against null would fail in the loop body (since Equals() just compares
// the raw pointer value of aLocalName to what AttrSlotIsTaken() would be
// checking.
for (const InternalAttr& attr : NonMappedAttrs()) {
for (const InternalAttr& attr : Attrs()) {
if (attr.mName.Equals(aLocalName)) {
return i;
}
++i;
}
} else {
for (const InternalAttr& attr : NonMappedAttrs()) {
for (const InternalAttr& attr : Attrs()) {
if (attr.mName.Equals(aLocalName, aNamespaceID)) {
return i;
}
@ -283,53 +226,12 @@ int32_t AttrArray::IndexOfAttr(const nsAtom* aLocalName,
return -1;
}
nsresult AttrArray::SetAndSwapMappedAttr(nsAtom* aLocalName,
nsAttrValue& aValue,
nsMappedAttributeElement* aContent,
bool* aHadValue) {
bool willAdd = true;
if (mImpl && mImpl->mMappedAttrs) {
willAdd = !mImpl->mMappedAttrs->GetAttr(aLocalName);
}
RefPtr<nsMappedAttributes> mapped = ModifiableMapped(aContent, willAdd);
mapped->SetAndSwapAttr(aLocalName, aValue, aHadValue);
return MakeMappedUnique(mapped);
}
nsresult AttrArray::SetMappedAttributeStyles(
mozilla::AttributeStyles* aNewStyles) {
MOZ_ASSERT(mImpl && mImpl->mMappedAttrs, "Should have mapped attrs here!");
if (aNewStyles == mImpl->mMappedAttrs->GetAttributeStyles()) {
return NS_OK;
}
RefPtr<nsMappedAttributes> mapped = ModifiableMapped(nullptr, false);
mapped->DropAttributeStylesReference();
mapped->SetAttributeStyles(aNewStyles);
return MakeMappedUnique(mapped);
}
nsresult AttrArray::DoUpdateMappedAttrRuleMapper(
nsMappedAttributeElement& aElement) {
MOZ_ASSERT(mImpl && mImpl->mMappedAttrs, "Should have mapped attrs here!");
// First two args don't matter if the assert holds.
RefPtr<nsMappedAttributes> mapped = ModifiableMapped(nullptr, false);
mapped->SetRuleMapper(aElement.GetAttributeMappingFunction());
return MakeMappedUnique(mapped);
}
void AttrArray::Compact() {
if (!mImpl) {
return;
}
if (!mImpl->mAttrCount && !mImpl->mMappedAttrs) {
if (!mImpl->mAttrCount && !mImpl->mMappedAttributeBits) {
mImpl.reset();
return;
}
@ -347,73 +249,12 @@ void AttrArray::Compact() {
mImpl.reset(impl);
}
uint32_t AttrArray::DoGetMappedAttrCount() const {
MOZ_ASSERT(mImpl && mImpl->mMappedAttrs);
return static_cast<uint32_t>(mImpl->mMappedAttrs->Count());
}
nsresult AttrArray::ForceMapped(nsMappedAttributeElement* aContent) {
RefPtr<nsMappedAttributes> mapped = ModifiableMapped(aContent, false, 0);
return MakeMappedUnique(mapped);
}
void AttrArray::ClearMappedServoStyle() {
if (mImpl && mImpl->mMappedAttrs) {
mImpl->mMappedAttrs->ClearServoStyle();
}
}
nsMappedAttributes* AttrArray::ModifiableMapped(
nsMappedAttributeElement* aContent, bool aWillAddAttr, int32_t aAttrCount) {
if (mImpl && mImpl->mMappedAttrs) {
return mImpl->mMappedAttrs->Clone(aWillAddAttr);
}
MOZ_ASSERT(aContent, "Trying to create modifiable without content");
nsMapRuleToAttributesFunc mapRuleFunc =
aContent->GetAttributeMappingFunction();
return new (aAttrCount) nsMappedAttributes(
aContent->OwnerDoc()->GetAttributeStyles(), mapRuleFunc);
}
nsresult AttrArray::MakeMappedUnique(nsMappedAttributes* aAttributes) {
NS_ASSERTION(aAttributes, "missing attributes");
if (!mImpl && !GrowBy(1)) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (!aAttributes->GetAttributeStyles()) {
// This doesn't currently happen, but it could if we do loading right
RefPtr<nsMappedAttributes> mapped(aAttributes);
mapped.swap(mImpl->mMappedAttrs);
return NS_OK;
}
RefPtr<nsMappedAttributes> mapped =
aAttributes->GetAttributeStyles()->UniqueMappedAttributes(aAttributes);
NS_ENSURE_TRUE(mapped, NS_ERROR_OUT_OF_MEMORY);
if (mapped != aAttributes) {
// Reset the stylesheet of aAttributes so that it doesn't spend time
// trying to remove itself from the hash. There is no risk that aAttributes
// is in the hash since it will always have come from ModifiableMapped,
// which never returns maps that are in the hash (such hashes are by
// nature not modifiable).
aAttributes->DropAttributeStylesReference();
}
mapped.swap(mImpl->mMappedAttrs);
return NS_OK;
}
nsresult AttrArray::EnsureCapacityToClone(const AttrArray& aOther) {
MOZ_ASSERT(!mImpl,
"AttrArray::EnsureCapacityToClone requires the array be empty "
"when called");
uint32_t attrCount = aOther.NonMappedAttrCount();
uint32_t attrCount = aOther.AttrCount();
if (!attrCount) {
return NS_OK;
}
@ -424,7 +265,7 @@ nsresult AttrArray::EnsureCapacityToClone(const AttrArray& aOther) {
static_cast<Impl*>(malloc(Impl::AllocationSizeForAttributes(attrCount))));
NS_ENSURE_TRUE(mImpl, NS_ERROR_OUT_OF_MEMORY);
mImpl->mMappedAttrs = nullptr;
mImpl->mMappedAttributeBits = 0;
mImpl->mCapacity = attrCount;
mImpl->mAttrCount = 0;
@ -480,7 +321,7 @@ bool AttrArray::GrowBy(uint32_t aGrowSize) {
// Set initial counts if we didn't have a buffer before
if (needToInitialize) {
mImpl->mMappedAttrs = nullptr;
mImpl->mMappedAttributeBits = 0;
mImpl->mAttrCount = 0;
}
@ -490,17 +331,13 @@ bool AttrArray::GrowBy(uint32_t aGrowSize) {
size_t AttrArray::SizeOfExcludingThis(
mozilla::MallocSizeOf aMallocSizeOf) const {
size_t n = 0;
if (mImpl) {
// Don't add the size taken by *mMappedAttrs because it's shared.
n += aMallocSizeOf(mImpl.get());
for (const InternalAttr& attr : NonMappedAttrs()) {
n += attr.mValue.SizeOfExcludingThis(aMallocSizeOf);
}
if (!mImpl) {
return 0;
}
size_t n = aMallocSizeOf(mImpl.get());
for (const InternalAttr& attr : Attrs()) {
n += attr.mValue.SizeOfExcludingThis(aMallocSizeOf);
}
return n;
}

View File

@ -22,12 +22,10 @@
#include "nsAttrValue.h"
#include "nsCaseTreatment.h"
class nsMappedAttributes;
class nsMappedAttributeElement;
namespace mozilla {
class AttributeStyles;
}
struct StyleLockedDeclarationBlock;
} // namespace mozilla
class AttrArray {
using BorrowedAttrInfo = mozilla::dom::BorrowedAttrInfo;
@ -36,11 +34,9 @@ class AttrArray {
AttrArray() = default;
~AttrArray() = default;
bool HasAttrs() const { return NonMappedAttrCount() || MappedAttrCount(); }
bool HasAttrs() const { return !!AttrCount(); }
uint32_t AttrCount() const {
return NonMappedAttrCount() + MappedAttrCount();
}
uint32_t AttrCount() const { return mImpl ? mImpl->mAttrCount : 0; }
const nsAttrValue* GetAttr(const nsAtom* aLocalName,
int32_t aNamespaceID = kNameSpaceID_None) const;
@ -61,6 +57,20 @@ class AttrArray {
nsresult SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue,
bool* aHadValue);
// This stores the argument and clears the pending mapped attribute evaluation
// bit, so after calling this IsPendingMappedAttributeEvaluation() is
// guaranteed to return false.
void SetMappedDeclarationBlock(
already_AddRefed<mozilla::StyleLockedDeclarationBlock>);
bool IsPendingMappedAttributeEvaluation() const {
return mImpl && mImpl->mMappedAttributeBits & 1;
}
mozilla::StyleLockedDeclarationBlock* GetMappedDeclarationBlock() const {
return mImpl ? mImpl->GetMappedDeclarationBlock() : nullptr;
}
// Remove the attr at position aPos. The value of the attr is placed in
// aValue; any value that was already in aValue is destroyed.
nsresult RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue);
@ -78,34 +88,27 @@ class AttrArray {
int32_t IndexOfAttr(const nsAtom* aLocalName,
int32_t aNamespaceID = kNameSpaceID_None) const;
// SetAndSwapMappedAttr swaps the current attribute value with aValue.
// If the attribute was unset, an empty value will be swapped into aValue
// and aHadValue will be set to false. Otherwise, aHadValue will be set to
// true.
nsresult SetAndSwapMappedAttr(nsAtom* aLocalName, nsAttrValue& aValue,
nsMappedAttributeElement* aContent,
bool* aHadValue);
// Update the rule mapping function on our mapped attributes, if we have any.
// We take a nsMappedAttributeElement, not a nsMapRuleToAttributesFunc,
// because the latter is defined in a header we can't include here.
nsresult UpdateMappedAttrRuleMapper(nsMappedAttributeElement& aElement) {
if (!mImpl || !mImpl->mMappedAttrs) {
return NS_OK;
}
return DoUpdateMappedAttrRuleMapper(aElement);
}
void Compact();
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
bool HasMappedAttrs() const { return !!GetMapped(); }
const nsMappedAttributes* GetMapped() const {
return mImpl ? mImpl->mMappedAttrs : nullptr;
// Mark the element as pending mapped attribute evaluation. This should be
// called when a mapped attribute is changed (regardless of connectedness).
bool MarkAsPendingPresAttributeEvaluation() {
// It'd be great to be able to assert that mImpl is non-null or we're the
// <body> element.
if (MOZ_UNLIKELY(!mImpl) && !GrowBy(1)) {
return false;
}
InfallibleMarkAsPendingPresAttributeEvaluation();
return true;
}
// Force this to have mapped attributes, even if those attributes are empty.
nsresult ForceMapped(nsMappedAttributeElement* aContent);
// See above.
void InfallibleMarkAsPendingPresAttributeEvaluation() {
MOZ_ASSERT(mImpl);
mImpl->mMappedAttributeBits |= 1;
}
// Clear the servo declaration block on the mapped attributes, if any
// Will assert off main thread
@ -158,8 +161,6 @@ class AttrArray {
return val && val->Equals(aValue, aCaseSensitive);
}
nsresult SetMappedAttributeStyles(mozilla::AttributeStyles* aNewStyles);
struct InternalAttr {
nsAttrName mName;
nsAttrValue mValue;
@ -169,20 +170,6 @@ class AttrArray {
AttrArray& operator=(const AttrArray& aOther) = delete;
private:
uint32_t NonMappedAttrCount() const { return mImpl ? mImpl->mAttrCount : 0; }
uint32_t MappedAttrCount() const {
return mImpl && mImpl->mMappedAttrs ? DoGetMappedAttrCount() : 0;
}
uint32_t DoGetMappedAttrCount() const;
// Returns a non-null zero-refcount object.
nsMappedAttributes* ModifiableMapped(nsMappedAttributeElement* aContent,
bool aWillAddAttr,
int32_t aAttrCount = 1);
nsresult MakeMappedUnique(nsMappedAttributes* aAttributes);
bool GrowBy(uint32_t aGrowSize);
// Tries to create an attribute, growing the buffer if needed, with the given
@ -195,30 +182,22 @@ class AttrArray {
template <typename Name>
nsresult AddNewAttribute(Name*, nsAttrValue&);
/**
* Guts of UpdateMappedAttrRuleMapper for the case when we have mapped attrs.
*/
nsresult DoUpdateMappedAttrRuleMapper(nsMappedAttributeElement& aElement);
#ifdef _MSC_VER
// Disable MSVC warning 'nonstandard extension used: zero-sized array in
// struct/union'
# pragma warning(push)
# pragma warning(disable : 4200)
#endif
class Impl {
public:
constexpr static size_t AllocationSizeForAttributes(uint32_t aAttrCount) {
return sizeof(Impl) + aAttrCount * sizeof(InternalAttr);
}
auto NonMappedAttrs() const {
mozilla::StyleLockedDeclarationBlock* GetMappedDeclarationBlock() const {
return reinterpret_cast<mozilla::StyleLockedDeclarationBlock*>(
mMappedAttributeBits & ~uintptr_t(1));
}
auto Attrs() const {
return mozilla::Span<const InternalAttr>{mBuffer, mAttrCount};
}
auto NonMappedAttrs() {
return mozilla::Span<InternalAttr>{mBuffer, mAttrCount};
}
auto Attrs() { return mozilla::Span<InternalAttr>{mBuffer, mAttrCount}; }
Impl(const Impl&) = delete;
Impl(Impl&&) = delete;
@ -227,23 +206,25 @@ class AttrArray {
uint32_t mAttrCount;
uint32_t mCapacity; // In number of InternalAttrs
// Manually refcounted.
nsMappedAttributes* mMappedAttrs;
// mMappedAttributeBits is a tagged pointer of a
// StyleLockedDeclarationBlock, which holds the style information that our
// attributes map to.
//
// If the lower bit is set, then our mapped attributes are dirty. This just
// means that we might have mapped attributes (or used to and no longer
// have), and are pending an update to recompute our declaration.
uintptr_t mMappedAttributeBits = 0;
// Allocated in the same buffer as `Impl`.
InternalAttr mBuffer[0];
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
mozilla::Span<InternalAttr> NonMappedAttrs() {
return mImpl ? mImpl->NonMappedAttrs() : mozilla::Span<InternalAttr>();
mozilla::Span<InternalAttr> Attrs() {
return mImpl ? mImpl->Attrs() : mozilla::Span<InternalAttr>();
}
mozilla::Span<const InternalAttr> NonMappedAttrs() const {
return mImpl ? mImpl->NonMappedAttrs()
: mozilla::Span<const InternalAttr>();
mozilla::Span<const InternalAttr> Attrs() const {
return mImpl ? mImpl->Attrs() : mozilla::Span<const InternalAttr>();
}
mozilla::UniquePtr<Impl> mImpl;

View File

@ -68,6 +68,7 @@
#include "mozilla/ExtensionPolicyService.h"
#include "mozilla/FullscreenChange.h"
#include "mozilla/GlobalStyleSheetCache.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/IdentifierMapEntry.h"
@ -8653,11 +8654,43 @@ already_AddRefed<Attr> Document::CreateAttributeNS(
return attribute.forget();
}
void Document::ResolveScheduledSVGPresAttrs() {
for (SVGElement* svg : mLazySVGPresElements) {
svg->UpdateContentDeclarationBlock();
void Document::ScheduleForPresAttrEvaluation(Element* aElement) {
MOZ_ASSERT(aElement->IsInComposedDoc());
DebugOnly<bool> inserted = mLazyPresElements.EnsureInserted(aElement);
MOZ_ASSERT(inserted);
if (aElement->HasServoData()) {
// TODO(emilio): RESTYLE_SELF is too strong, there should be no need to
// re-selector-match, but right now this is needed to pick up the new mapped
// attributes. We need something like RESTYLE_STYLE_ATTRIBUTE but for mapped
// attributes.
nsLayoutUtils::PostRestyleEvent(aElement, RestyleHint::RESTYLE_SELF,
nsChangeHint(0));
}
mLazySVGPresElements.Clear();
}
void Document::UnscheduleForPresAttrEvaluation(Element* aElement) {
mLazyPresElements.Remove(aElement);
}
void Document::DoResolveScheduledPresAttrs() {
MOZ_ASSERT(!mLazyPresElements.IsEmpty());
for (Element* el : mLazyPresElements) {
MOZ_ASSERT(el->IsInComposedDoc(),
"Un-schedule when removing from the document");
MOZ_ASSERT(el->IsPendingMappedAttributeEvaluation());
if (auto* svg = SVGElement::FromNode(el)) {
// SVG does its own (very similar) thing, for now at least.
svg->UpdateMappedDeclarationBlock();
} else {
MappedDeclarationsBuilder builder(*el, *this,
el->GetMappedAttributeStyle());
auto function = el->GetAttributeMappingFunction();
function(builder);
el->SetMappedDeclarationBlock(builder.TakeDeclarationBlock());
}
MOZ_ASSERT(!el->IsPendingMappedAttributeEvaluation());
}
mLazyPresElements.Clear();
}
already_AddRefed<nsSimpleContentList> Document::BlockedNodesByClassifier()

View File

@ -1379,25 +1379,25 @@ class Document : public nsINode,
void NotifyLayerManagerRecreated();
/**
* Add an SVG element to the list of elements that need
* their mapped attributes resolved to a Servo declaration block.
*
* These are weak pointers, please manually unschedule them when an element
* is removed.
*/
void ScheduleSVGForPresAttrEvaluation(SVGElement* aSVG) {
mLazySVGPresElements.Insert(aSVG);
}
// Add an element to the list of elements that need their mapped attributes
// resolved to a declaration block.
//
// These are weak pointers, manually unschedule them when an element is
// removed from the tree.
void ScheduleForPresAttrEvaluation(Element* aElement);
// Unschedule an element scheduled by ScheduleFrameRequestCallback (e.g. for
// when it is destroyed)
void UnscheduleSVGForPresAttrEvaluation(SVGElement* aSVG) {
mLazySVGPresElements.Remove(aSVG);
}
// Un-schedule an element scheduled by ScheduleForPresAttrEvaluation,
// generally when it's unbound from the tree.
void UnscheduleForPresAttrEvaluation(Element* aElement);
// Resolve all SVG pres attrs scheduled in ScheduleSVGForPresAttrEvaluation
void ResolveScheduledSVGPresAttrs();
// Resolve all presentational attributes scheduled in
// ScheduleForPresAttrEvaluation
void ResolveScheduledPresAttrs() {
if (mLazyPresElements.IsEmpty()) {
return;
}
DoResolveScheduledPresAttrs();
}
Maybe<ClientInfo> GetClientInfo() const;
Maybe<ClientState> GetClientState() const;
@ -1564,6 +1564,8 @@ class Document : public nsINode,
void DoUnblockOnload();
void DoResolveScheduledPresAttrs();
void RetrieveRelevantHeaders(nsIChannel* aChannel);
void TryChannelCharset(nsIChannel* aChannel, int32_t& aCharsetSource,
@ -5257,10 +5259,9 @@ class Document : public nsINode,
RefPtr<DOMStyleSheetSetList> mStyleSheetSetList;
// We lazily calculate declaration blocks for SVG elements with mapped
// attributes in Servo mode. This list contains all elements which need lazy
// resolution.
nsTHashSet<SVGElement*> mLazySVGPresElements;
// We lazily calculate declaration blocks for elements with mapped
// attributes. This set contains all elements which need lazy resolution.
nsTHashSet<Element*> mLazyPresElements;
nsTHashSet<RefPtr<nsAtom>> mLanguagesUsed;

View File

@ -43,6 +43,7 @@
#include "mozilla/Likely.h"
#include "mozilla/LinkedList.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/NotNull.h"
#include "mozilla/PointerLockManager.h"
@ -1859,6 +1860,9 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
}
if (IsInComposedDoc()) {
if (IsPendingMappedAttributeEvaluation()) {
aContext.OwnerDoc().ScheduleForPresAttrEvaluation(this);
}
// Connected callback must be enqueued whenever a custom element becomes
// connected.
if (CustomElementData* data = GetCustomElementData()) {
@ -2062,8 +2066,7 @@ void Element::UnbindFromTree(bool aNullParent) {
if (document) {
// Disconnected must be enqueued whenever a connected custom element becomes
// disconnected.
CustomElementData* data = GetCustomElementData();
if (data) {
if (CustomElementData* data = GetCustomElementData()) {
if (data->mState == CustomElementData::State::eCustom) {
nsContentUtils::EnqueueLifecycleCallback(
ElementCallbackType::eDisconnected, this, {});
@ -2074,6 +2077,10 @@ void Element::UnbindFromTree(bool aNullParent) {
}
}
if (IsPendingMappedAttributeEvaluation()) {
document->UnscheduleForPresAttrEvaluation(this);
}
if (HasLastRememberedBSize() || HasLastRememberedISize()) {
// Need to remove the last remembered size at the next ResizeObserver
// opportunity, so observe the element. But if already observed, we still
@ -2170,11 +2177,24 @@ nsresult Element::SetInlineStyleDeclaration(DeclarationBlock& aDeclaration,
NS_IMETHODIMP_(bool)
Element::IsAttributeMapped(const nsAtom* aAttribute) const { return false; }
nsMapRuleToAttributesFunc Element::GetAttributeMappingFunction() const {
return &MapNoAttributesInto;
}
void Element::MapNoAttributesInto(mozilla::MappedDeclarationsBuilder&) {}
nsChangeHint Element::GetAttributeChangeHint(const nsAtom* aAttribute,
int32_t aModType) const {
return nsChangeHint(0);
}
void Element::SetMappedDeclarationBlock(
already_AddRefed<StyleLockedDeclarationBlock> aDeclarations) {
MOZ_ASSERT(IsPendingMappedAttributeEvaluation());
mAttrs.SetMappedDeclarationBlock(std::move(aDeclarations));
MOZ_ASSERT(!IsPendingMappedAttributeEvaluation());
}
bool Element::FindAttributeDependence(const nsAtom* aAttribute,
const MappedAttributeEntry* const aMaps[],
uint32_t aMapCount) {
@ -2550,11 +2570,10 @@ nsresult Element::SetAttrAndNotify(
nsIPrincipal* aSubjectPrincipal, uint8_t aModType, bool aFireMutation,
bool aNotify, bool aCallAfterSetAttr, Document* aComposedDocument,
const mozAutoDocUpdate& aGuard) {
nsresult rv;
nsMutationGuard::DidMutate();
// Copy aParsedValue for later use since it will be lost when we call
// SetAndSwapMappedAttr below
// SetAndSwapAttr below
nsAttrValue valueForAfterSetAttr;
if (aCallAfterSetAttr || GetCustomElementData()) {
valueForAfterSetAttr.SetTo(aParsedValue);
@ -2570,20 +2589,19 @@ nsresult Element::SetAttrAndNotify(
hadDirAuto = HasDirAuto(); // already takes bdi into account
}
// XXXbz Perhaps we should push up the attribute mapping function
// stuff to Element?
if (!IsAttributeMapped(aName) ||
!SetAndSwapMappedAttribute(aName, aParsedValue, &oldValueSet, &rv)) {
rv = mAttrs.SetAndSwapAttr(aName, aParsedValue, &oldValueSet);
MOZ_TRY(mAttrs.SetAndSwapAttr(aName, aParsedValue, &oldValueSet));
if (IsAttributeMapped(aName) && !IsPendingMappedAttributeEvaluation()) {
mAttrs.InfallibleMarkAsPendingPresAttributeEvaluation();
if (Document* doc = GetComposedDoc()) {
doc->ScheduleForPresAttrEvaluation(this);
}
}
} else {
RefPtr<mozilla::dom::NodeInfo> ni;
ni = mNodeInfo->NodeInfoManager()->GetNodeInfo(aName, aPrefix, aNamespaceID,
ATTRIBUTE_NODE);
rv = mAttrs.SetAndSwapAttr(ni, aParsedValue, &oldValueSet);
RefPtr<mozilla::dom::NodeInfo> ni =
mNodeInfo->NodeInfoManager()->GetNodeInfo(aName, aPrefix, aNamespaceID,
ATTRIBUTE_NODE);
MOZ_TRY(mAttrs.SetAndSwapAttr(ni, aParsedValue, &oldValueSet));
}
NS_ENSURE_SUCCESS(rv, rv);
PostIdMaybeChange(aNamespaceID, aName, &valueForAfterSetAttr);
@ -2723,12 +2741,6 @@ bool Element::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
return false;
}
bool Element::SetAndSwapMappedAttribute(nsAtom* aName, nsAttrValue& aValue,
bool* aValueWasSet, nsresult* aRetval) {
*aRetval = NS_OK;
return false;
}
void Element::BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
const nsAttrValue* aValue, bool aNotify) {
if (aNamespaceID == kNameSpaceID_None) {
@ -2887,14 +2899,21 @@ nsresult Element::UnsetAttr(int32_t aNameSpaceID, nsAtom* aName, bool aNotify) {
bool hadValidDir = false;
bool hadDirAuto = false;
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
hadValidDir = HasValidDir() || IsHTMLElement(nsGkAtoms::bdi);
hadDirAuto = HasDirAuto(); // already takes bdi into account
if (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::dir) {
hadValidDir = HasValidDir() || IsHTMLElement(nsGkAtoms::bdi);
hadDirAuto = HasDirAuto(); // already takes bdi into account
}
if (IsAttributeMapped(aName) && !IsPendingMappedAttributeEvaluation()) {
mAttrs.InfallibleMarkAsPendingPresAttributeEvaluation();
if (Document* doc = GetComposedDoc()) {
doc->ScheduleForPresAttrEvaluation(this);
}
}
}
nsAttrValue oldValue;
nsresult rv = mAttrs.RemoveAttrAt(index, oldValue);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_TRY(mAttrs.RemoveAttrAt(index, oldValue));
PostIdMaybeChange(aNameSpaceID, aName, nullptr);

View File

@ -93,7 +93,6 @@ class nsIPrincipal;
class nsIScreen;
class nsIScrollableFrame;
class nsIURI;
class nsMappedAttributes;
class nsPresContext;
class nsWindowSizes;
struct JSContext;
@ -105,6 +104,7 @@ class nsGetterAddRefs;
namespace mozilla {
class DeclarationBlock;
class MappedDeclarationsBuilder;
class ErrorResult;
class OOMReporter;
class SMILAttr;
@ -144,6 +144,8 @@ typedef nsTHashMap<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>
} // namespace dom
} // namespace mozilla
using nsMapRuleToAttributesFunc = void (*)(mozilla::MappedDeclarationsBuilder&);
// Declared here because of include hell.
extern "C" bool Servo_Element_IsDisplayContents(const mozilla::dom::Element*);
@ -387,11 +389,15 @@ class Element : public FragmentOrElement {
/**
* Get the mapped attributes, if any, for this element.
*/
const nsMappedAttributes* GetMappedAttributes() const {
return mAttrs.GetMapped();
StyleLockedDeclarationBlock* GetMappedAttributeStyle() const {
return mAttrs.GetMappedDeclarationBlock();
}
void ClearMappedServoStyle() { mAttrs.ClearMappedServoStyle(); }
bool IsPendingMappedAttributeEvaluation() const {
return mAttrs.IsPendingMappedAttributeEvaluation();
}
void SetMappedDeclarationBlock(already_AddRefed<StyleLockedDeclarationBlock>);
/**
* InlineStyleDeclarationWillChange is called before SetInlineStyleDeclaration
@ -457,14 +463,16 @@ class Element : public FragmentOrElement {
virtual nsIMozBrowserFrame* GetAsMozBrowserFrame() { return nullptr; }
/**
* Is the attribute named stored in the mapped attributes?
*
* // XXXbz we use this method in HasAttributeDependentStyle, so svg
* returns true here even though it stores nothing in the mapped
* attributes.
* Is the attribute named aAttribute a mapped attribute?
*/
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const;
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(bool aNullParent = true) override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
static void MapNoAttributesInto(mozilla::MappedDeclarationsBuilder&);
/**
* Get a hint that tells the style system what to do when
* an attribute on this node changes, if something needs to happen
@ -806,10 +814,6 @@ class Element : public FragmentOrElement {
void UpdateEditableState(bool aNotify) override;
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(bool aNullParent = true) override;
/**
* Normalizes an attribute name and returns it as a nodeinfo if an attribute
* with that name exists. This method is intended for character case
@ -1893,27 +1897,6 @@ class Element : public FragmentOrElement {
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult);
/**
* Try to set the attribute as a mapped attribute, if applicable. This will
* only be called for attributes that are in the null namespace and only on
* attributes that returned true when passed to IsAttributeMapped. The
* caller will not try to set the attr in any other way if this method
* returns true (the value of aRetval does not matter for that purpose).
*
* @param aName the name of the attribute
* @param aValue the nsAttrValue to set. Will be swapped with the existing
* value of the attribute if the attribute already exists.
* @param [out] aValueWasSet If the attribute was not set previously,
* aValue will be swapped with an empty attribute
* and aValueWasSet will be set to false. Otherwise,
* aValueWasSet will be set to true and aValue will
* contain the previous value set.
* @param [out] aRetval the nsresult status of the operation, if any.
* @return true if the setting was attempted, false otherwise.
*/
virtual bool SetAndSwapMappedAttribute(nsAtom* aName, nsAttrValue& aValue,
bool* aValueWasSet, nsresult* aRetval);
/**
* Hook that is called by Element::SetAttr to allow subclasses to
* deal with attribute sets. This will only be called after we verify that

View File

@ -93,8 +93,6 @@ EXPORTS += [
"nsJSEnvironment.h",
"nsJSUtils.h",
"nsLineBreaker.h",
"nsMappedAttributeElement.h",
"nsMappedAttributes.h",
"nsNameSpaceManager.h",
"nsNodeInfoManager.h",
"nsPIDOMWindow.h",
@ -411,8 +409,6 @@ UNIFIED_SOURCES += [
"nsJSEnvironment.cpp",
"nsJSUtils.cpp",
"nsLineBreaker.cpp",
"nsMappedAttributeElement.cpp",
"nsMappedAttributes.cpp",
"nsMimeTypeArray.cpp",
"nsNameSpaceManager.cpp",
"nsNoDataProtocolContentPolicy.cpp",

View File

@ -340,7 +340,6 @@
#include "nsJSUtils.h"
#include "nsLayoutUtils.h"
#include "nsLiteralString.h"
#include "nsMappedAttributes.h"
#include "nsMargin.h"
#include "nsMimeTypes.h"
#include "nsNameSpaceManager.h"
@ -1966,7 +1965,6 @@ void nsContentUtils::Shutdown() {
}
TextControlState::Shutdown();
nsMappedAttributes::Shutdown();
}
/**

View File

@ -45,7 +45,6 @@
#include "nsHTMLDocument.h"
#include "nsPIWindowRoot.h"
#include "nsLayoutUtils.h"
#include "nsMappedAttributes.h"
#include "nsView.h"
#include "nsBaseWidget.h"
#include "nsQueryObject.h"
@ -1067,20 +1066,11 @@ void nsFrameLoader::MarginsChanged() {
// that needs to be updated
if (Document* doc = docShell->GetDocument()) {
for (nsINode* cur = doc; cur; cur = cur->GetNextNode()) {
if (cur->IsHTMLElement(nsGkAtoms::body)) {
static_cast<HTMLBodyElement*>(cur)->ClearMappedServoStyle();
if (auto* body = HTMLBodyElement::FromNode(cur)) {
body->FrameMarginsChanged();
}
}
}
// Trigger a restyle if there's a prescontext
// FIXME: This could do something much less expensive.
if (nsPresContext* presContext = docShell->GetPresContext()) {
// rebuild, because now the same nsMappedAttributes* will produce
// a different style
presContext->RebuildAllStyleData(nsChangeHint(0),
RestyleHint::RestyleSubtree());
}
}
bool nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,

View File

@ -1,32 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsMappedAttributeElement.h"
#include "nsMappedAttributes.h"
#include "mozilla/dom/Document.h"
bool nsMappedAttributeElement::SetAndSwapMappedAttribute(nsAtom* aName,
nsAttrValue& aValue,
bool* aValueWasSet,
nsresult* aRetval) {
*aRetval = mAttrs.SetAndSwapMappedAttr(aName, aValue, this, aValueWasSet);
return true;
}
nsMapRuleToAttributesFunc
nsMappedAttributeElement::GetAttributeMappingFunction() const {
return &MapNoAttributesInto;
}
void nsMappedAttributeElement::MapNoAttributesInto(
const nsMappedAttributes*, mozilla::MappedDeclarations&) {}
void nsMappedAttributeElement::NodeInfoChanged(Document* aOldDoc) {
if (mAttrs.HasMappedAttrs()) {
mAttrs.SetMappedAttributeStyles(OwnerDoc()->GetAttributeStyles());
}
nsMappedAttributeElementBase::NodeInfoChanged(aOldDoc);
}

View File

@ -1,49 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* nsMappedAttributeElement is the base for elements supporting style mapped
* attributes via nsMappedAttributes (HTML and MathML).
*/
#ifndef NS_MAPPEDATTRIBUTEELEMENT_H_
#define NS_MAPPEDATTRIBUTEELEMENT_H_
#include "mozilla/Attributes.h"
#include "nsStyledElement.h"
namespace mozilla {
class MappedDeclarations;
}
class nsMappedAttributes;
struct nsRuleData;
using nsMapRuleToAttributesFunc = void (*)(
const nsMappedAttributes* aAttributes, mozilla::MappedDeclarations&);
using nsMappedAttributeElementBase = nsStyledElement;
class nsMappedAttributeElement : public nsMappedAttributeElementBase {
protected:
explicit nsMappedAttributeElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: nsMappedAttributeElementBase(std::move(aNodeInfo)) {}
public:
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
static void MapNoAttributesInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
virtual bool SetAndSwapMappedAttribute(nsAtom* aName, nsAttrValue& aValue,
bool* aValueWasSet,
nsresult* aRetval) override;
virtual void NodeInfoChanged(mozilla::dom::Document* aOldDoc) override;
};
#endif // NS_MAPPEDATTRIBUTEELEMENT_H_

View File

@ -1,258 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* A unique per-element set of attributes that is used as an
* nsIStyleRule; used to implement presentational attributes.
*/
#include "nsMappedAttributes.h"
#include "mozilla/Assertions.h"
#include "mozilla/AttributeStyles.h"
#include "mozilla/DeclarationBlock.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MemoryReporting.h"
using namespace mozilla;
bool nsMappedAttributes::sShuttingDown = false;
nsTArray<void*>* nsMappedAttributes::sCachedMappedAttributeAllocations =
nullptr;
void nsMappedAttributes::Shutdown() {
sShuttingDown = true;
if (sCachedMappedAttributeAllocations) {
for (uint32_t i = 0; i < sCachedMappedAttributeAllocations->Length(); ++i) {
void* cachedValue = (*sCachedMappedAttributeAllocations)[i];
::operator delete(cachedValue);
}
}
delete sCachedMappedAttributeAllocations;
sCachedMappedAttributeAllocations = nullptr;
}
nsMappedAttributes::nsMappedAttributes(AttributeStyles* aAttrStyles,
nsMapRuleToAttributesFunc aMapRuleFunc)
: mAttrCount(0),
mAttrStyles(aAttrStyles),
mRuleMapper(aMapRuleFunc),
mServoStyle(nullptr) {
MOZ_ASSERT(mRefCnt == 0); // Ensure caching works as expected.
}
nsMappedAttributes::nsMappedAttributes(const nsMappedAttributes& aCopy)
: mAttrCount(aCopy.mAttrCount),
mAttrStyles(aCopy.mAttrStyles),
mRuleMapper(aCopy.mRuleMapper),
// This is only called by ::Clone, which is used to create independent
// nsMappedAttributes objects which should not share a DeclarationBlock
mServoStyle(nullptr) {
MOZ_ASSERT(mBufferSize >= aCopy.mAttrCount, "can't fit attributes");
MOZ_ASSERT(mRefCnt == 0); // Ensure caching works as expected.
uint32_t i = 0;
for (const InternalAttr& attr : aCopy.Attrs()) {
new (&mBuffer[i++]) InternalAttr(attr);
}
}
nsMappedAttributes::~nsMappedAttributes() {
if (mAttrStyles) {
mAttrStyles->DropMappedAttributes(this);
}
for (InternalAttr& attr : Attrs()) {
attr.~InternalAttr();
}
}
nsMappedAttributes* nsMappedAttributes::Clone(bool aWillAddAttr) {
uint32_t extra = aWillAddAttr ? 1 : 0;
// This will call the overridden operator new
return new (mAttrCount + extra) nsMappedAttributes(*this);
}
void* nsMappedAttributes::operator new(size_t aSize,
uint32_t aAttrCount) noexcept(true) {
size_t size = aSize + aAttrCount * sizeof(InternalAttr);
if (sCachedMappedAttributeAllocations) {
void* cached = sCachedMappedAttributeAllocations->SafeElementAt(aAttrCount);
if (cached) {
(*sCachedMappedAttributeAllocations)[aAttrCount] = nullptr;
return cached;
}
}
void* newAttrs = ::operator new(size);
#ifdef DEBUG
static_cast<nsMappedAttributes*>(newAttrs)->mBufferSize = aAttrCount;
#endif
return newAttrs;
}
void nsMappedAttributes::LastRelease() {
if (!sShuttingDown) {
if (!sCachedMappedAttributeAllocations) {
sCachedMappedAttributeAllocations = new nsTArray<void*>();
}
// Ensure the cache array is at least mAttrCount + 1 long and
// that each item is either null or pointing to a cached item.
// The size of the array is capped because mapped attributes are defined
// statically in element implementations.
sCachedMappedAttributeAllocations->SetCapacity(mAttrCount + 1);
for (uint32_t i = sCachedMappedAttributeAllocations->Length();
i < (uint32_t(mAttrCount) + 1); ++i) {
sCachedMappedAttributeAllocations->AppendElement(nullptr);
}
if (!(*sCachedMappedAttributeAllocations)[mAttrCount]) {
void* memoryToCache = this;
this->~nsMappedAttributes();
(*sCachedMappedAttributeAllocations)[mAttrCount] = memoryToCache;
return;
}
}
delete this;
}
void nsMappedAttributes::SetAndSwapAttr(nsAtom* aAttrName, nsAttrValue& aValue,
bool* aValueWasSet) {
MOZ_ASSERT(aAttrName, "null name");
*aValueWasSet = false;
uint32_t i;
for (i = 0; i < mAttrCount && !mBuffer[i].mName.IsSmaller(aAttrName); ++i) {
if (mBuffer[i].mName.Equals(aAttrName)) {
mBuffer[i].mValue.SwapValueWith(aValue);
*aValueWasSet = true;
return;
}
}
MOZ_ASSERT(mBufferSize >= mAttrCount + 1, "can't fit attributes");
if (mAttrCount != i) {
memmove(&mBuffer[i + 1], &mBuffer[i],
(mAttrCount - i) * sizeof(InternalAttr));
}
new (&mBuffer[i].mName) nsAttrName(aAttrName);
new (&mBuffer[i].mValue) nsAttrValue();
mBuffer[i].mValue.SwapValueWith(aValue);
++mAttrCount;
}
const nsAttrValue* nsMappedAttributes::GetAttr(const nsAtom* aAttrName) const {
MOZ_ASSERT(aAttrName, "null name");
for (const InternalAttr& attr : Attrs()) {
if (attr.mName.Equals(aAttrName)) {
return &attr.mValue;
}
}
return nullptr;
}
const nsAttrValue* nsMappedAttributes::GetAttr(
const nsAString& aAttrName) const {
for (const InternalAttr& attr : Attrs()) {
if (attr.mName.Atom()->Equals(aAttrName)) {
return &attr.mValue;
}
}
return nullptr;
}
bool nsMappedAttributes::Equals(const nsMappedAttributes* aOther) const {
if (this == aOther) {
return true;
}
if (mRuleMapper != aOther->mRuleMapper || mAttrCount != aOther->mAttrCount) {
return false;
}
uint32_t i;
for (i = 0; i < mAttrCount; ++i) {
if (!mBuffer[i].mName.Equals(aOther->mBuffer[i].mName) ||
!mBuffer[i].mValue.Equals(aOther->mBuffer[i].mValue)) {
return false;
}
}
return true;
}
PLDHashNumber nsMappedAttributes::HashValue() const {
PLDHashNumber hash = HashGeneric(mRuleMapper);
for (const InternalAttr& attr : Attrs()) {
hash = AddToHash(hash, attr.mName.HashValue(), attr.mValue.HashValue());
}
return hash;
}
void nsMappedAttributes::SetAttributeStyles(AttributeStyles* aAttrStyles) {
MOZ_ASSERT(!mAttrStyles,
"Should either drop the sheet reference manually, "
"or drop the mapped attributes");
mAttrStyles = aAttrStyles; // not ref counted
}
void nsMappedAttributes::RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue) {
mBuffer[aPos].mValue.SwapValueWith(aValue);
mBuffer[aPos].~InternalAttr();
memmove(&mBuffer[aPos], &mBuffer[aPos + 1],
(mAttrCount - aPos - 1) * sizeof(InternalAttr));
mAttrCount--;
}
const nsAttrName* nsMappedAttributes::GetExistingAttrNameFromQName(
const nsAString& aName) const {
for (const InternalAttr& attr : Attrs()) {
if (attr.mName.Atom()->Equals(aName)) {
return &attr.mName;
}
}
return nullptr;
}
int32_t nsMappedAttributes::IndexOfAttr(const nsAtom* aLocalName) const {
for (uint32_t i = 0; i < mAttrCount; ++i) {
if (mBuffer[i].mName.Equals(aLocalName)) {
return i;
}
}
return -1;
}
size_t nsMappedAttributes::SizeOfIncludingThis(
MallocSizeOf aMallocSizeOf) const {
MOZ_ASSERT(mBufferSize >= mAttrCount, "can't fit attributes");
size_t n = aMallocSizeOf(this);
for (const InternalAttr& attr : Attrs()) {
n += attr.mValue.SizeOfExcludingThis(aMallocSizeOf);
}
return n;
}
void nsMappedAttributes::LazilyResolveServoDeclaration(dom::Document* aDoc) {
MOZ_ASSERT(!mServoStyle,
"LazilyResolveServoDeclaration should not be called if "
"mServoStyle is already set");
if (mRuleMapper) {
MappedDeclarations declarations(
aDoc, Servo_DeclarationBlock_CreateEmpty().Consume());
(*mRuleMapper)(this, declarations);
mServoStyle = declarations.TakeDeclarationBlock();
}
}

View File

@ -1,117 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* A unique per-element set of attributes that is used as an
* nsIStyleRule; used to implement presentational attributes.
*/
#ifndef nsMappedAttributes_h___
#define nsMappedAttributes_h___
#include "AttrArray.h"
#include "nsMappedAttributeElement.h"
#include "mozilla/Attributes.h"
#include "mozilla/ServoBindingTypes.h"
#include "mozilla/MemoryReporting.h"
class nsAtom;
namespace mozilla {
class AttributeStyles;
}
class nsMappedAttributes final {
using InternalAttr = AttrArray::InternalAttr;
public:
nsMappedAttributes(mozilla::AttributeStyles*, nsMapRuleToAttributesFunc);
// Do not return null.
void* operator new(size_t size, uint32_t aAttrCount = 1) noexcept(true);
nsMappedAttributes* Clone(bool aWillAddAttr);
NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(nsMappedAttributes, LastRelease())
void SetAndSwapAttr(nsAtom* aAttrName, nsAttrValue& aValue,
bool* aValueWasSet);
const nsAttrValue* GetAttr(const nsAtom* aAttrName) const;
const nsAttrValue* GetAttr(const nsAString& aAttrName) const;
uint32_t Count() const { return mAttrCount; }
bool Equals(const nsMappedAttributes* aAttributes) const;
PLDHashNumber HashValue() const;
void DropAttributeStylesReference() { mAttrStyles = nullptr; }
void SetAttributeStyles(mozilla::AttributeStyles*);
mozilla::AttributeStyles* GetAttributeStyles() { return mAttrStyles; }
void SetRuleMapper(nsMapRuleToAttributesFunc aRuleMapper) {
mRuleMapper = aRuleMapper;
}
auto Attrs() const {
return mozilla::Span<const InternalAttr>{mBuffer, mAttrCount};
}
auto Attrs() { return mozilla::Span<InternalAttr>{mBuffer, mAttrCount}; }
const nsAttrName* NameAt(uint32_t aPos) const {
NS_ASSERTION(aPos < mAttrCount, "out-of-bounds");
return &Attrs()[aPos].mName;
}
const nsAttrValue* AttrAt(uint32_t aPos) const {
NS_ASSERTION(aPos < mAttrCount, "out-of-bounds");
return &Attrs()[aPos].mValue;
}
// Remove the attr at position aPos. The value of the attr is placed in
// aValue; any value that was already in aValue is destroyed.
void RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue);
const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
int32_t IndexOfAttr(const nsAtom* aLocalName) const;
// Apply the contained mapper to the contained set of servo rules,
// unless the servo rules have already been initialized.
void LazilyResolveServoDeclaration(mozilla::dom::Document* aDocument);
// Obtain the contained servo declaration block
// May return null if called before the inner block
// has been (lazily) resolved
const mozilla::StyleLockedDeclarationBlock* GetServoStyle() const {
return mServoStyle;
}
void ClearServoStyle() {
MOZ_ASSERT(NS_IsMainThread());
mServoStyle = nullptr;
}
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
static void Shutdown();
private:
void LastRelease();
nsMappedAttributes(const nsMappedAttributes& aCopy);
~nsMappedAttributes();
uint16_t mAttrCount;
#ifdef DEBUG
uint16_t mBufferSize;
#endif
mozilla::AttributeStyles* mAttrStyles; // weak
nsMapRuleToAttributesFunc mRuleMapper;
RefPtr<mozilla::StyleLockedDeclarationBlock> mServoStyle;
InternalAttr mBuffer[0];
static bool sShuttingDown;
// We're caching some memory to avoid trashing the allocator.
// The memory stored at index N can hold N attribute values.
static nsTArray<void*>* sCachedMappedAttributeAllocations;
};
#endif /* nsMappedAttributes_h___ */

View File

@ -228,7 +228,7 @@ function testHtmlSerializer_1 () {
encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
encoder.setNode(node);
out = encoder.encodeToString();
expected = '<hr id="shortattr6" noshade="noshade">';
expected = '<hr noshade="noshade" id="shortattr6">';
is(out, expected, "test short attr #6");
node = document.getElementById('shortattr7');

View File

@ -6,10 +6,9 @@
#include "mozilla/dom/HTMLBRElement.h"
#include "mozilla/dom/HTMLBRElementBinding.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsAttrValueInlines.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(BR)
@ -42,14 +41,14 @@ bool HTMLBRElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
aMaybeScriptedPrincipal, aResult);
}
void HTMLBRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty_clear)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::clear);
if (value && value->Type() == nsAttrValue::eEnum)
aDecls.SetKeywordValue(eCSSProperty_clear, value->GetEnumValue());
void HTMLBRElement::MapAttributesIntoRule(MappedDeclarationsBuilder& aBuilder) {
if (!aBuilder.PropertyIsSet(eCSSProperty_clear)) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::clear);
if (value && value->Type() == nsAttrValue::eEnum) {
aBuilder.SetKeywordValue(eCSSProperty_clear, value->GetEnumValue());
}
}
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -65,8 +65,7 @@ class HTMLBRElement final : public nsGenericHTMLElement {
private:
virtual ~HTMLBRElement();
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -10,7 +10,7 @@
#include "mozilla/AttributeStyles.h"
#include "mozilla/EditorBase.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/TextEditor.h"
#include "mozilla/dom/BindContext.h"
#include "mozilla/dom/Document.h"
@ -20,7 +20,6 @@
#include "nsPresContext.h"
#include "DocumentInlines.h"
#include "nsDocShell.h"
#include "nsMappedAttributes.h"
#include "nsIDocShell.h"
#include "nsGlobalWindow.h"
@ -66,7 +65,7 @@ bool HTMLBodyElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLBodyElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MappedDeclarationsBuilder& aBuilder) {
// This is the one place where we try to set the same property
// multiple times in presentation attributes. Servo does not support
// querying if a property is set (because that is O(n) behavior
@ -84,143 +83,143 @@ void HTMLBodyElement::MapAttributesIntoRule(
const nsAttrValue* value;
// if marginwidth/marginheight are set, reflect them as 'margin'
value = aAttributes->GetAttr(nsGkAtoms::marginwidth);
value = aBuilder.GetAttr(nsGkAtoms::marginwidth);
if (value && value->Type() == nsAttrValue::eInteger) {
bodyMarginWidth = value->GetIntegerValue();
if (bodyMarginWidth < 0) {
bodyMarginWidth = 0;
}
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left,
(float)bodyMarginWidth);
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right,
(float)bodyMarginWidth);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_left,
(float)bodyMarginWidth);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_right,
(float)bodyMarginWidth);
}
value = aAttributes->GetAttr(nsGkAtoms::marginheight);
value = aBuilder.GetAttr(nsGkAtoms::marginheight);
if (value && value->Type() == nsAttrValue::eInteger) {
bodyMarginHeight = value->GetIntegerValue();
if (bodyMarginHeight < 0) {
bodyMarginHeight = 0;
}
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top,
(float)bodyMarginHeight);
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom,
(float)bodyMarginHeight);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_top,
(float)bodyMarginHeight);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_bottom,
(float)bodyMarginHeight);
}
// topmargin (IE-attribute)
if (bodyMarginHeight == -1) {
value = aAttributes->GetAttr(nsGkAtoms::topmargin);
value = aBuilder.GetAttr(nsGkAtoms::topmargin);
if (value && value->Type() == nsAttrValue::eInteger) {
bodyTopMargin = value->GetIntegerValue();
if (bodyTopMargin < 0) {
bodyTopMargin = 0;
}
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top,
(float)bodyTopMargin);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_top,
(float)bodyTopMargin);
}
}
// bottommargin (IE-attribute)
if (bodyMarginHeight == -1) {
value = aAttributes->GetAttr(nsGkAtoms::bottommargin);
value = aBuilder.GetAttr(nsGkAtoms::bottommargin);
if (value && value->Type() == nsAttrValue::eInteger) {
bodyBottomMargin = value->GetIntegerValue();
if (bodyBottomMargin < 0) {
bodyBottomMargin = 0;
}
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom,
(float)bodyBottomMargin);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_bottom,
(float)bodyBottomMargin);
}
}
// leftmargin (IE-attribute)
if (bodyMarginWidth == -1) {
value = aAttributes->GetAttr(nsGkAtoms::leftmargin);
value = aBuilder.GetAttr(nsGkAtoms::leftmargin);
if (value && value->Type() == nsAttrValue::eInteger) {
bodyLeftMargin = value->GetIntegerValue();
if (bodyLeftMargin < 0) {
bodyLeftMargin = 0;
}
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left,
(float)bodyLeftMargin);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_left,
(float)bodyLeftMargin);
}
}
// rightmargin (IE-attribute)
if (bodyMarginWidth == -1) {
value = aAttributes->GetAttr(nsGkAtoms::rightmargin);
value = aBuilder.GetAttr(nsGkAtoms::rightmargin);
if (value && value->Type() == nsAttrValue::eInteger) {
bodyRightMargin = value->GetIntegerValue();
if (bodyRightMargin < 0) {
bodyRightMargin = 0;
}
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right,
(float)bodyRightMargin);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_right,
(float)bodyRightMargin);
}
}
// if marginwidth or marginheight is set in the <frame> and not set in the
// <body> reflect them as margin in the <body>
if (bodyMarginWidth == -1 || bodyMarginHeight == -1) {
if (nsDocShell* ds = nsDocShell::Cast(aDecls.Document()->GetDocShell())) {
if (nsDocShell* ds = nsDocShell::Cast(aBuilder.Document().GetDocShell())) {
CSSIntSize margins = ds->GetFrameMargins();
int32_t frameMarginWidth = margins.width;
int32_t frameMarginHeight = margins.height;
if (bodyMarginWidth == -1 && frameMarginWidth >= 0) {
if (bodyLeftMargin == -1) {
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left,
(float)frameMarginWidth);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_left,
(float)frameMarginWidth);
}
if (bodyRightMargin == -1) {
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right,
(float)frameMarginWidth);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_right,
(float)frameMarginWidth);
}
}
if (bodyMarginHeight == -1 && frameMarginHeight >= 0) {
if (bodyTopMargin == -1) {
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top,
(float)frameMarginHeight);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_top,
(float)frameMarginHeight);
}
if (bodyBottomMargin == -1) {
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom,
(float)frameMarginHeight);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_bottom,
(float)frameMarginHeight);
}
}
}
}
// When display if first asked for, go ahead and get our colors set up.
if (AttributeStyles* attrStyles = aDecls.Document()->GetAttributeStyles()) {
if (AttributeStyles* attrStyles = aBuilder.Document().GetAttributeStyles()) {
nscolor color;
value = aAttributes->GetAttr(nsGkAtoms::link);
value = aBuilder.GetAttr(nsGkAtoms::link);
if (value && value->GetColorValue(color)) {
attrStyles->SetLinkColor(color);
}
value = aAttributes->GetAttr(nsGkAtoms::alink);
value = aBuilder.GetAttr(nsGkAtoms::alink);
if (value && value->GetColorValue(color)) {
attrStyles->SetActiveLinkColor(color);
}
value = aAttributes->GetAttr(nsGkAtoms::vlink);
value = aBuilder.GetAttr(nsGkAtoms::vlink);
if (value && value->GetColorValue(color)) {
attrStyles->SetVisitedLinkColor(color);
}
}
if (!aDecls.PropertyIsSet(eCSSProperty_color)) {
if (!aBuilder.PropertyIsSet(eCSSProperty_color)) {
// color: color
nscolor color;
value = aAttributes->GetAttr(nsGkAtoms::text);
value = aBuilder.GetAttr(nsGkAtoms::text);
if (value && value->GetColorValue(color)) {
aDecls.SetColorValue(eCSSProperty_color, color);
aBuilder.SetColorValue(eCSSProperty_color, color);
}
}
nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapBackgroundAttributesInto(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
nsMapRuleToAttributesFunc HTMLBodyElement::GetAttributeMappingFunction() const {
@ -281,26 +280,17 @@ bool HTMLBodyElement::IsEventAttributeNameInternal(nsAtom* aName) {
}
nsresult HTMLBodyElement::BindToTree(BindContext& aContext, nsINode& aParent) {
nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
NS_ENSURE_SUCCESS(rv, rv);
return mAttrs.ForceMapped(this);
mAttrs.MarkAsPendingPresAttributeEvaluation();
return nsGenericHTMLElement::BindToTree(aContext, aParent);
}
void HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
nsIPrincipal* aSubjectPrincipal,
bool aNotify) {
nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aOldValue,
aSubjectPrincipal, aNotify);
// If the last mapped attribute was removed, don't clear the
// nsMappedAttributes, our style can still depend on the containing frame
// element.
//
// FIXME(emilio, bug 1839333): Is this true? We don't store containing frame
// stuff in nsMappedAttributes / AttributeStyles, maybe we can remove this?
if (!aValue && IsAttributeMapped(aName)) {
Unused << mAttrs.ForceMapped(this);
void HTMLBodyElement::FrameMarginsChanged() {
MOZ_ASSERT(IsInComposedDoc());
if (IsPendingMappedAttributeEvaluation()) {
return;
}
if (mAttrs.MarkAsPendingPresAttributeEvaluation()) {
OwnerDoc()->ScheduleForPresAttrEvaluation(this);
}
}

View File

@ -88,37 +88,27 @@ class HTMLBodyElement final : public nsGenericHTMLElement {
SetHTMLAttr(nsGkAtoms::background, aBackground, aError);
}
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual already_AddRefed<EditorBase> GetAssociatedEditor() override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
already_AddRefed<EditorBase> GetAssociatedEditor() override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
virtual bool IsEventAttributeNameInternal(nsAtom* aName) override;
bool IsEventAttributeNameInternal(nsAtom* aName) override;
nsresult BindToTree(BindContext&, nsINode& aParent) override;
virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
/**
* Called when an attribute has just been changed
*/
virtual void AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
nsIPrincipal* aSubjectPrincipal,
bool aNotify) override;
void FrameMarginsChanged();
protected:
virtual ~HTMLBodyElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace dom

View File

@ -725,9 +725,9 @@ nsChangeHint HTMLCanvasElement::GetAttributeChangeHint(const nsAtom* aAttribute,
}
void HTMLCanvasElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MapAspectRatioInto(aAttributes, aDecls);
MapCommonAttributesInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
MapAspectRatioInto(aBuilder);
MapCommonAttributesInto(aBuilder);
}
nsMapRuleToAttributesFunc HTMLCanvasElement::GetAttributeMappingFunction()

View File

@ -266,8 +266,7 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsresult CopyInnerTo(HTMLCanvasElement* aDest);
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
/*
* Helpers called by various users of Canvas

View File

@ -7,7 +7,6 @@
#include "HTMLDivElement.h"
#include "nsGenericHTMLElement.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
#include "mozilla/dom/HTMLDivElementBinding.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Div)
@ -36,9 +35,9 @@ bool HTMLDivElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLDivElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
MapDivAlignAttributeInto(aBuilder);
MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -24,24 +24,21 @@ class HTMLDivElement final : public nsGenericHTMLElement {
SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
}
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
protected:
virtual ~HTMLDivElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -18,7 +18,6 @@
# include "mozilla/EventDispatcher.h"
# include "mozilla/dom/Event.h"
#endif
#include "mozilla/dom/HTMLObjectElement.h"
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Embed)
@ -179,24 +178,22 @@ bool HTMLEmbedElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
aMaybeScriptedPrincipal, aResult);
}
static void MapAttributesIntoRuleBase(const nsMappedAttributes* aAttributes,
MappedDeclarations& aDecls) {
nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aDecls);
static void MapAttributesIntoRuleBase(MappedDeclarationsBuilder& aBuilder) {
nsGenericHTMLElement::MapImageMarginAttributeInto(aBuilder);
nsGenericHTMLElement::MapImageSizeAttributesInto(aBuilder);
nsGenericHTMLElement::MapImageAlignAttributeInto(aBuilder);
}
static void MapAttributesIntoRuleExceptHidden(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MapAttributesIntoRuleBase(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aAttributes,
aDecls);
MappedDeclarationsBuilder& aBuilder) {
MapAttributesIntoRuleBase(aBuilder);
nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aBuilder);
}
void HTMLEmbedElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MapAttributesIntoRuleBase(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
MapAttributesIntoRuleBase(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -33,28 +33,27 @@ class HTMLEmbedElement final : public nsGenericHTMLElement,
}
// EventTarget
virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
virtual void UnbindFromTree(bool aNullParent = true) override;
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(bool aNullParent = true) override;
virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
int32_t* aTabIndex) override;
bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
int32_t* aTabIndex) override;
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual ElementState IntrinsicState() const override;
virtual void DestroyContent() override;
ElementState IntrinsicState() const override;
void DestroyContent() override;
// nsObjectLoadingContent
virtual uint32_t GetCapabilities() const override;
uint32_t GetCapabilities() const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsresult CopyInnerTo(HTMLEmbedElement* aDest);
@ -106,25 +105,21 @@ class HTMLEmbedElement final : public nsGenericHTMLElement,
// Override for nsImageLoadingContent.
nsIContent* AsContent() override { return this; }
virtual void AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
nsIPrincipal* aSubjectPrincipal,
bool aNotify) override;
virtual void OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
const nsAttrValueOrString& aValue,
bool aNotify) override;
void AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aOldValue,
nsIPrincipal* aSubjectPrincipal, bool aNotify) override;
void OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
const nsAttrValueOrString& aValue,
bool aNotify) override;
private:
~HTMLEmbedElement();
nsContentPolicyType GetContentPolicyType() const override;
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
/**
* This function is called by AfterSetAttr and OnAttrSetButNotChanged.

View File

@ -7,9 +7,8 @@
#include "HTMLFontElement.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLFontElementBinding.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsAttrValueInlines.h"
#include "nsMappedAttributes.h"
#include "nsContentUtils.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Font)
@ -48,41 +47,43 @@ bool HTMLFontElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLFontElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MappedDeclarationsBuilder& aBuilder) {
// face: string list
if (!aDecls.PropertyIsSet(eCSSProperty_font_family)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::face);
if (!aBuilder.PropertyIsSet(eCSSProperty_font_family)) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::face);
if (value && value->Type() == nsAttrValue::eString &&
!value->IsEmptyString()) {
aDecls.SetFontFamily(NS_ConvertUTF16toUTF8(value->GetStringValue()));
aBuilder.SetFontFamily(NS_ConvertUTF16toUTF8(value->GetStringValue()));
}
}
// size: int
if (!aDecls.PropertyIsSet(eCSSProperty_font_size)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::size);
if (value && value->Type() == nsAttrValue::eInteger)
aDecls.SetKeywordValue(eCSSProperty_font_size, value->GetIntegerValue());
}
if (!aDecls.PropertyIsSet(eCSSProperty_color)) {
// color: color
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::color);
nscolor color;
if (value && value->GetColorValue(color)) {
aDecls.SetColorValue(eCSSProperty_color, color);
if (!aBuilder.PropertyIsSet(eCSSProperty_font_size)) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::size);
if (value && value->Type() == nsAttrValue::eInteger) {
aBuilder.SetKeywordValue(eCSSProperty_font_size,
value->GetIntegerValue());
}
}
if (aDecls.Document()->GetCompatibilityMode() == eCompatibility_NavQuirks) {
if (!aBuilder.PropertyIsSet(eCSSProperty_color)) {
// color: color
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::color);
nscolor color;
if (value && value->GetColorValue(color)) {
aBuilder.SetColorValue(eCSSProperty_color, color);
}
}
if (aBuilder.Document().GetCompatibilityMode() == eCompatibility_NavQuirks) {
// Make <a><font color="red">text</font></a> give the text a red underline
// in quirks mode. The StyleTextDecorationLine_COLOR_OVERRIDE flag only
// affects quirks mode rendering.
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::color);
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::color);
nscolor color;
if (value && value->GetColorValue(color)) {
aDecls.SetTextDecorationColorOverride();
aBuilder.SetTextDecorationColorOverride();
}
}
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -29,24 +29,21 @@ class HTMLFontElement final : public nsGenericHTMLElement {
SetHTMLAttr(nsGkAtoms::size, aSize, aError);
}
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
protected:
virtual ~HTMLFontElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -28,11 +28,11 @@ class HTMLFrameElement final : public nsGenericHTMLFrameElement {
NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLFrameElement, frame)
// nsIContent
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
// WebIDL API
void GetFrameBorder(DOMString& aFrameBorder) const {
@ -92,12 +92,7 @@ class HTMLFrameElement final : public nsGenericHTMLFrameElement {
protected:
virtual ~HTMLFrameElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
};
} // namespace mozilla::dom

View File

@ -9,7 +9,7 @@
#include "nsCSSProps.h"
#include "nsStyleConsts.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(HR)
@ -52,56 +52,55 @@ bool HTMLHRElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
aMaybeScriptedPrincipal, aResult);
}
void HTMLHRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations& aDecls) {
void HTMLHRElement::MapAttributesIntoRule(MappedDeclarationsBuilder& aBuilder) {
bool noshade = false;
const nsAttrValue* colorValue = aAttributes->GetAttr(nsGkAtoms::color);
const nsAttrValue* colorValue = aBuilder.GetAttr(nsGkAtoms::color);
nscolor color;
bool colorIsSet = colorValue && colorValue->GetColorValue(color);
if (colorIsSet) {
noshade = true;
} else {
noshade = !!aAttributes->GetAttr(nsGkAtoms::noshade);
noshade = !!aBuilder.GetAttr(nsGkAtoms::noshade);
}
// align: enum
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::align);
if (value && value->Type() == nsAttrValue::eEnum) {
// Map align attribute into auto side margins
switch (StyleTextAlign(value->GetEnumValue())) {
case StyleTextAlign::Left:
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left, 0.0f);
aDecls.SetAutoValueIfUnset(eCSSProperty_margin_right);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_left, 0.0f);
aBuilder.SetAutoValueIfUnset(eCSSProperty_margin_right);
break;
case StyleTextAlign::Right:
aDecls.SetAutoValueIfUnset(eCSSProperty_margin_left);
aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right, 0.0f);
aBuilder.SetAutoValueIfUnset(eCSSProperty_margin_left);
aBuilder.SetPixelValueIfUnset(eCSSProperty_margin_right, 0.0f);
break;
case StyleTextAlign::Center:
aDecls.SetAutoValueIfUnset(eCSSProperty_margin_left);
aDecls.SetAutoValueIfUnset(eCSSProperty_margin_right);
aBuilder.SetAutoValueIfUnset(eCSSProperty_margin_left);
aBuilder.SetAutoValueIfUnset(eCSSProperty_margin_right);
break;
default:
MOZ_ASSERT_UNREACHABLE("Unknown <hr align> value");
break;
}
}
if (!aDecls.PropertyIsSet(eCSSProperty_height)) {
if (!aBuilder.PropertyIsSet(eCSSProperty_height)) {
// size: integer
if (noshade) {
// noshade case: size is set using the border
aDecls.SetAutoValue(eCSSProperty_height);
aBuilder.SetAutoValue(eCSSProperty_height);
} else {
// normal case
// the height includes the top and bottom borders that are initially 1px.
// for size=1, html.css has a special case rule that makes this work by
// removing all but the top border.
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::size);
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::size);
if (value && value->Type() == nsAttrValue::eInteger) {
aDecls.SetPixelValue(eCSSProperty_height,
(float)value->GetIntegerValue());
aBuilder.SetPixelValue(eCSSProperty_height,
(float)value->GetIntegerValue());
} // else use default value from html.css
}
}
@ -112,7 +111,7 @@ void HTMLHRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
// if a size is set, use half of it per side, otherwise, use 1px per side
float sizePerSide;
bool allSides = true;
value = aAttributes->GetAttr(nsGkAtoms::size);
value = aBuilder.GetAttr(nsGkAtoms::size);
if (value && value->Type() == nsAttrValue::eInteger) {
sizePerSide = (float)value->GetIntegerValue() / 2.0f;
if (sizePerSide < 1.0f) {
@ -125,24 +124,27 @@ void HTMLHRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
} else {
sizePerSide = 1.0f; // default to a 2px high line
}
aDecls.SetPixelValueIfUnset(eCSSProperty_border_top_width, sizePerSide);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_top_width, sizePerSide);
if (allSides) {
aDecls.SetPixelValueIfUnset(eCSSProperty_border_right_width, sizePerSide);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_bottom_width,
sizePerSide);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_left_width, sizePerSide);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_right_width,
sizePerSide);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_bottom_width,
sizePerSide);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_left_width,
sizePerSide);
}
if (!aDecls.PropertyIsSet(eCSSProperty_border_top_style))
aDecls.SetKeywordValue(eCSSProperty_border_top_style,
StyleBorderStyle::Solid);
if (!aBuilder.PropertyIsSet(eCSSProperty_border_top_style)) {
aBuilder.SetKeywordValue(eCSSProperty_border_top_style,
StyleBorderStyle::Solid);
}
if (allSides) {
aDecls.SetKeywordValueIfUnset(eCSSProperty_border_right_style,
StyleBorderStyle::Solid);
aDecls.SetKeywordValueIfUnset(eCSSProperty_border_bottom_style,
StyleBorderStyle::Solid);
aDecls.SetKeywordValueIfUnset(eCSSProperty_border_left_style,
StyleBorderStyle::Solid);
aBuilder.SetKeywordValueIfUnset(eCSSProperty_border_right_style,
StyleBorderStyle::Solid);
aBuilder.SetKeywordValueIfUnset(eCSSProperty_border_bottom_style,
StyleBorderStyle::Solid);
aBuilder.SetKeywordValueIfUnset(eCSSProperty_border_left_style,
StyleBorderStyle::Solid);
// If it would be noticeable, set the border radius to
// 10000px on all corners; this triggers the clamping to make
@ -151,18 +153,17 @@ void HTMLHRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
for (const nsCSSPropertyID* props =
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius);
*props != eCSSProperty_UNKNOWN; ++props) {
aDecls.SetPixelValueIfUnset(*props, 10000.0f);
aBuilder.SetPixelValueIfUnset(*props, 10000.0f);
}
}
}
// color: a color
// (we got the color attribute earlier)
if (colorIsSet) {
aDecls.SetColorValueIfUnset(eCSSProperty_color, color);
aBuilder.SetColorValueIfUnset(eCSSProperty_color, color);
}
nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
MapWidthAttributeInto(aBuilder);
MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -8,8 +8,6 @@
#define mozilla_dom_HTMLHRElement_h
#include "nsGenericHTMLElement.h"
#include "nsMappedAttributes.h"
#include "nsAttrValueInlines.h"
namespace mozilla::dom {
@ -20,14 +18,13 @@ class HTMLHRElement final : public nsGenericHTMLElement {
// nsISupports
NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLHRElement, nsGenericHTMLElement)
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
// WebIDL API
void GetAlign(nsAString& aValue) const {
@ -66,12 +63,10 @@ class HTMLHRElement final : public nsGenericHTMLElement {
protected:
virtual ~HTMLHRElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -7,12 +7,8 @@
#include "mozilla/dom/HTMLHeadingElement.h"
#include "mozilla/dom/HTMLHeadingElementBinding.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/StaticPrefs_accessibility.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
#include "mozAutoDocUpdate.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Heading)
@ -41,9 +37,9 @@ bool HTMLHeadingElement::ParseAttribute(int32_t aNamespaceID,
}
void HTMLHeadingElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
nsGenericHTMLElement::MapDivAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -64,8 +64,7 @@ class HTMLHeadingElement final : public nsGenericHTMLElement {
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -9,13 +9,11 @@
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLIFrameElementBinding.h"
#include "mozilla/dom/FeaturePolicy.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/StaticPrefs_dom.h"
#include "nsMappedAttributes.h"
#include "nsAttrValueInlines.h"
#include "nsError.h"
#include "nsStyleConsts.h"
#include "nsContentUtils.h"
#include "nsSandboxFlags.h"
#include "nsNetUtil.h"
@ -108,25 +106,25 @@ bool HTMLIFrameElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLIFrameElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MappedDeclarationsBuilder& aBuilder) {
// frameborder: 0 | 1 (| NO | YES in quirks mode)
// If frameborder is 0 or No, set border to 0
// else leave it as the value set in html.css
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::frameborder);
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::frameborder);
if (value && value->Type() == nsAttrValue::eEnum) {
auto frameborder = static_cast<FrameBorderProperty>(value->GetEnumValue());
if (FrameBorderProperty::No == frameborder ||
FrameBorderProperty::Zero == frameborder) {
aDecls.SetPixelValueIfUnset(eCSSProperty_border_top_width, 0.0f);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_right_width, 0.0f);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_bottom_width, 0.0f);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_left_width, 0.0f);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_top_width, 0.0f);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_right_width, 0.0f);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_bottom_width, 0.0f);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_left_width, 0.0f);
}
}
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapImageSizeAttributesInto(aBuilder);
nsGenericHTMLElement::MapImageAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -173,8 +173,7 @@ class HTMLIFrameElement final : public nsGenericHTMLFrameElement {
bool aNotify) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
static const DOMTokenListSupportedToken sSupportedSandboxTokens[];

View File

@ -14,7 +14,6 @@
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsMappedAttributes.h"
#include "nsSize.h"
#include "mozilla/dom/Document.h"
#include "nsImageFrame.h"
@ -43,7 +42,7 @@
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/Maybe.h"
#include "mozilla/RestyleManager.h"
@ -258,12 +257,12 @@ bool HTMLImageElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLImageElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MapImageAlignAttributeInto(aAttributes, aDecls);
MapImageBorderAttributeInto(aAttributes, aDecls);
MapImageMarginAttributeInto(aAttributes, aDecls);
MapImageSizeAttributesInto(aAttributes, aDecls, MapAspectRatio::Yes);
MapCommonAttributesInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
MapImageAlignAttributeInto(aBuilder);
MapImageBorderAttributeInto(aBuilder);
MapImageMarginAttributeInto(aBuilder);
MapImageSizeAttributesInto(aBuilder, MapAspectRatio::Yes);
MapCommonAttributesInto(aBuilder);
}
nsChangeHint HTMLImageElement::GetAttributeChangeHint(const nsAtom* aAttribute,
@ -1343,15 +1342,14 @@ void HTMLImageElement::StopLazyLoading(StartLoading aStartLoading) {
}
}
const nsMappedAttributes* HTMLImageElement::GetMappedAttributesFromSource()
const {
if (!IsInPicture() || !mResponsiveSelector ||
!mResponsiveSelector->Content()) {
const StyleLockedDeclarationBlock*
HTMLImageElement::GetMappedAttributesFromSource() const {
if (!IsInPicture() || !mResponsiveSelector) {
return nullptr;
}
const auto* source =
HTMLSourceElement::FromNode(mResponsiveSelector->Content());
HTMLSourceElement::FromNodeOrNull(mResponsiveSelector->Content());
if (!source) {
return nullptr;
}

View File

@ -271,7 +271,7 @@ class HTMLImageElement final : public nsGenericHTMLElement,
// This is used when restyling, for retrieving the extra style from the source
// element.
const nsMappedAttributes* GetMappedAttributesFromSource() const;
const StyleLockedDeclarationBlock* GetMappedAttributesFromSource() const;
protected:
virtual ~HTMLImageElement();
@ -380,8 +380,7 @@ class HTMLImageElement final : public nsGenericHTMLElement,
private:
bool SourceElementMatches(Element* aSourceElement);
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
/**
* This function is called by AfterSetAttr and OnAttrSetButNotChanged.
* It will not be called if the value is being unset.

View File

@ -53,7 +53,6 @@
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsMappedAttributes.h"
#include "nsIFormControl.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLDataListElement.h"
@ -75,7 +74,7 @@
#include "mozilla/ContentEvents.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/TextControlState.h"
#include "mozilla/TextEditor.h"
@ -4469,30 +4468,32 @@ void HTMLInputElement::HandleTypeChange(FormControlType aNewType,
RecomputeDirectionality(this, aNotify);
}
if (oldType == FormControlType::InputImage) {
// We're no longer an image input. Cancel our image requests, if we have
// any.
CancelImageRequests(aNotify);
// And we should update our mapped attribute mapping function.
mAttrs.UpdateMappedAttrRuleMapper(*this);
} else if (mType == FormControlType::InputImage) {
if (aNotify) {
// We just got switched to be an image input; we should see
// whether we have an image to load;
if (oldType == FormControlType::InputImage ||
mType == FormControlType::InputImage) {
if (oldType == FormControlType::InputImage) {
// We're no longer an image input. Cancel our image requests, if we have
// any.
CancelImageRequests(aNotify);
} else if (aNotify) {
// We just got switched to be an image input; we should see whether we
// have an image to load;
nsAutoString src;
if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
if (GetAttr(nsGkAtoms::src, src)) {
// Mark channel as urgent-start before load image if the image load is
// initaiated by a user interaction.
// initiated by a user interaction.
mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
LoadImage(src, false, aNotify, eImageLoadType_Normal,
mSrcTriggeringPrincipal);
}
}
// And we should update our mapped attribute mapping function.
mAttrs.UpdateMappedAttrRuleMapper(*this);
// We should update our mapped attribute mapping function.
if (mAttrs.HasAttrs() && !mAttrs.IsPendingMappedAttributeEvaluation()) {
mAttrs.InfallibleMarkAsPendingPresAttributeEvaluation();
if (auto* doc = GetComposedDoc()) {
doc->ScheduleForPresAttrEvaluation(this);
}
}
}
if (mType == FormControlType::InputPassword && IsInComposedDoc()) {
@ -5248,19 +5249,17 @@ bool HTMLInputElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLInputElement::ImageInputMapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MappedDeclarationsBuilder& aBuilder) {
nsGenericHTMLFormControlElementWithState::MapImageBorderAttributeInto(
aAttributes, aDecls);
aBuilder);
nsGenericHTMLFormControlElementWithState::MapImageMarginAttributeInto(
aAttributes, aDecls);
aBuilder);
nsGenericHTMLFormControlElementWithState::MapImageSizeAttributesInto(
aAttributes, aDecls, MapAspectRatio::Yes);
aBuilder, MapAspectRatio::Yes);
// Images treat align as "float"
nsGenericHTMLFormControlElementWithState::MapImageAlignAttributeInto(
aAttributes, aDecls);
nsGenericHTMLFormControlElementWithState::MapCommonAttributesInto(aAttributes,
aDecls);
aBuilder);
nsGenericHTMLFormControlElementWithState::MapCommonAttributesInto(aBuilder);
}
nsChangeHint HTMLInputElement::GetAttributeChangeHint(const nsAtom* aAttribute,

View File

@ -1565,8 +1565,7 @@ class HTMLInputElement final : public TextControlElement,
bool mHasPatternAttribute : 1;
private:
static void ImageInputMapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations&);
static void ImageInputMapAttributesIntoRule(MappedDeclarationsBuilder&);
/**
* Returns true if this input's type will fire a DOM "change" event when it

View File

@ -7,11 +7,10 @@
#include "mozilla/dom/HTMLLIElement.h"
#include "mozilla/dom/HTMLLIElementBinding.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsAttrValueInlines.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(LI)
@ -53,25 +52,25 @@ bool HTMLLIElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
aMaybeScriptedPrincipal, aResult);
}
void HTMLLIElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty_list_style_type)) {
void HTMLLIElement::MapAttributesIntoRule(MappedDeclarationsBuilder& aBuilder) {
if (!aBuilder.PropertyIsSet(eCSSProperty_list_style_type)) {
// type: enum
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
if (value && value->Type() == nsAttrValue::eEnum)
aDecls.SetKeywordValue(eCSSProperty_list_style_type,
value->GetEnumValue());
}
// Map <li value=INTEGER> to 'counter-set: list-item INTEGER'.
const nsAttrValue* attrVal = aAttributes->GetAttr(nsGkAtoms::value);
if (attrVal && attrVal->Type() == nsAttrValue::eInteger) {
if (!aDecls.PropertyIsSet(eCSSProperty_counter_set)) {
aDecls.SetCounterSetListItem(attrVal->GetIntegerValue());
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::type);
if (value && value->Type() == nsAttrValue::eEnum) {
aBuilder.SetKeywordValue(eCSSProperty_list_style_type,
value->GetEnumValue());
}
}
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
// Map <li value=INTEGER> to 'counter-set: list-item INTEGER'.
const nsAttrValue* attrVal = aBuilder.GetAttr(nsGkAtoms::value);
if (attrVal && attrVal->Type() == nsAttrValue::eInteger) {
if (!aBuilder.PropertyIsSet(eCSSProperty_counter_set)) {
aBuilder.SetCounterSetListItem(attrVal->GetIntegerValue());
}
}
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -21,14 +21,13 @@ class HTMLLIElement final : public nsGenericHTMLElement {
// nsISupports
NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLLIElement, nsGenericHTMLElement)
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
// WebIDL API
void GetType(DOMString& aType) { GetHTMLAttr(nsGkAtoms::type, aType); }
@ -43,12 +42,10 @@ class HTMLLIElement final : public nsGenericHTMLElement {
protected:
virtual ~HTMLLIElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -7,7 +7,6 @@
#include "mozilla/dom/HTMLMarqueeElement.h"
#include "nsGenericHTMLElement.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/dom/HTMLMarqueeElementBinding.h"
#include "mozilla/dom/CustomEvent.h"
@ -127,11 +126,11 @@ void HTMLMarqueeElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
}
void HTMLMarqueeElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapBGColorInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
nsGenericHTMLElement::MapImageMarginAttributeInto(aBuilder);
nsGenericHTMLElement::MapImageSizeAttributesInto(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
nsGenericHTMLElement::MapBGColorInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -104,11 +104,10 @@ class HTMLMarqueeElement final : public nsGenericHTMLElement {
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
virtual void AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
nsIPrincipal* aMaybeScriptedPrincipal,
bool aNotify) override;
void AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
const nsAttrValue* aValue, const nsAttrValue* aOldValue,
nsIPrincipal* aMaybeScriptedPrincipal,
bool aNotify) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
@ -121,8 +120,7 @@ class HTMLMarqueeElement final : public nsGenericHTMLElement {
JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
void DispatchEventToShadowRoot(const nsAString& aEventTypeArg);
};

View File

@ -232,16 +232,12 @@ bool HTMLObjectElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLObjectElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
nsGenericHTMLFormControlElement::MapImageAlignAttributeInto(aAttributes,
aDecls);
nsGenericHTMLFormControlElement::MapImageBorderAttributeInto(aAttributes,
aDecls);
nsGenericHTMLFormControlElement::MapImageMarginAttributeInto(aAttributes,
aDecls);
nsGenericHTMLFormControlElement::MapImageSizeAttributesInto(aAttributes,
aDecls);
nsGenericHTMLFormControlElement::MapCommonAttributesInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
MapImageAlignAttributeInto(aBuilder);
MapImageBorderAttributeInto(aBuilder);
MapImageMarginAttributeInto(aBuilder);
MapImageSizeAttributesInto(aBuilder);
MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -188,8 +188,7 @@ class HTMLObjectElement final : public nsGenericHTMLFormControlElement,
JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
/**
* This function is called by AfterSetAttr and OnAttrSetButNotChanged.

View File

@ -5,26 +5,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/HTMLOptionsCollection.h"
#include "HTMLOptGroupElement.h"
#include "mozAutoDocUpdate.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Element.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/dom/HTMLFormSubmission.h"
#include "mozilla/dom/HTMLOptionElement.h"
#include "mozilla/dom/HTMLOptionsCollectionBinding.h"
#include "mozilla/dom/HTMLOptionElement.h"
#include "mozilla/dom/HTMLSelectElement.h"
#include "nsContentCreatorFunctions.h"
#include "nsError.h"
#include "nsGkAtoms.h"
#include "mozilla/dom/Document.h"
#include "nsIFormControlFrame.h"
#include "nsLayoutUtils.h"
#include "nsMappedAttributes.h"
#include "nsServiceManagerUtils.h"
#include "nsStyleConsts.h"
#include "jsfriendapi.h"
namespace mozilla::dom {

View File

@ -7,9 +7,8 @@
#include "mozilla/dom/HTMLParagraphElement.h"
#include "mozilla/dom/HTMLParagraphElementBinding.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Paragraph)
@ -33,9 +32,9 @@ bool HTMLParagraphElement::ParseAttribute(int32_t aNamespaceID,
}
void HTMLParagraphElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
nsGenericHTMLElement::MapDivAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -23,15 +23,14 @@ class HTMLParagraphElement final : public nsGenericHTMLElement {
NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLParagraphElement,
nsGenericHTMLElement)
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
// WebIDL API
void GetAlign(nsAString& aValue) { GetHTMLAttr(nsGkAtoms::align, aValue); }
@ -42,12 +41,10 @@ class HTMLParagraphElement final : public nsGenericHTMLElement {
protected:
virtual ~HTMLParagraphElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -7,11 +7,10 @@
#include "mozilla/dom/HTMLPreElement.h"
#include "mozilla/dom/HTMLPreElementBinding.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsAttrValueInlines.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Pre)
@ -36,15 +35,14 @@ bool HTMLPreElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLPreElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty_white_space)) {
// wrap: empty
if (aAttributes->GetAttr(nsGkAtoms::wrap))
aDecls.SetKeywordValue(eCSSProperty_white_space,
MappedDeclarationsBuilder& aBuilder) {
// wrap: empty
if (aBuilder.GetAttr(nsGkAtoms::wrap)) {
aBuilder.SetKeywordValue(eCSSProperty_white_space,
StyleWhiteSpace::PreWrap);
}
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -21,15 +21,14 @@ class HTMLPreElement final : public nsGenericHTMLElement {
// nsISupports
NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLPreElement, nsGenericHTMLElement)
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
// WebIDL API
int32_t Width() const { return GetIntAttr(nsGkAtoms::width, 0); }
@ -40,12 +39,10 @@ class HTMLPreElement final : public nsGenericHTMLElement {
protected:
virtual ~HTMLPreElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*>) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -16,7 +16,7 @@
#include "mozilla/dom/HTMLOptionElement.h"
#include "mozilla/dom/HTMLSelectElementBinding.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/Maybe.h"
#include "nsContentCreatorFunctions.h"
#include "nsContentList.h"
@ -30,7 +30,6 @@
#include "nsListControlFrame.h"
#include "nsISelectControlFrame.h"
#include "nsLayoutUtils.h"
#include "nsMappedAttributes.h"
#include "mozilla/PresState.h"
#include "nsServiceManagerUtils.h"
#include "nsStyleConsts.h"
@ -1167,11 +1166,10 @@ bool HTMLSelectElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLSelectElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MappedDeclarationsBuilder& aBuilder) {
nsGenericHTMLFormControlElementWithState::MapImageAlignAttributeInto(
aAttributes, aDecls);
nsGenericHTMLFormControlElementWithState::MapCommonAttributesInto(aAttributes,
aDecls);
aBuilder);
nsGenericHTMLFormControlElementWithState::MapCommonAttributesInto(aBuilder);
}
nsChangeHint HTMLSelectElement::GetAttributeChangeHint(const nsAtom* aAttribute,

View File

@ -540,8 +540,7 @@ class HTMLSelectElement final : public nsGenericHTMLFormControlElementWithState,
nsString mPreviewValue;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace dom

View File

@ -14,10 +14,6 @@
#include "mozilla/dom/HTMLQuoteElementBinding.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/MappedDeclarations.h"
#include "nsAttrValueInlines.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
#include "nsContentUtils.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIURI.h"
@ -34,7 +30,7 @@ void HTMLSharedElement::GetHref(nsAString& aValue) {
MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::base),
"This should only get called for <base> elements");
nsAutoString href;
GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
GetAttr(nsGkAtoms::href, href);
nsCOMPtr<nsIURI> uri;
Document* doc = OwnerDoc();

View File

@ -9,12 +9,11 @@
#include "mozilla/dom/HTMLOListElementBinding.h"
#include "mozilla/dom/HTMLUListElementBinding.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsGenericHTMLElement.h"
#include "nsAttrValueInlines.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(SharedList)
@ -67,28 +66,28 @@ bool HTMLSharedListElement::ParseAttribute(
}
void HTMLSharedListElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty_list_style_type)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
MappedDeclarationsBuilder& aBuilder) {
if (!aBuilder.PropertyIsSet(eCSSProperty_list_style_type)) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::type);
if (value && value->Type() == nsAttrValue::eEnum) {
aDecls.SetKeywordValue(eCSSProperty_list_style_type,
value->GetEnumValue());
aBuilder.SetKeywordValue(eCSSProperty_list_style_type,
value->GetEnumValue());
}
}
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
void HTMLSharedListElement::MapOLAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty_counter_reset)) {
const nsAttrValue* startAttr = aAttributes->GetAttr(nsGkAtoms::start);
MappedDeclarationsBuilder& aBuilder) {
if (!aBuilder.PropertyIsSet(eCSSProperty_counter_reset)) {
const nsAttrValue* startAttr = aBuilder.GetAttr(nsGkAtoms::start);
bool haveStart = startAttr && startAttr->Type() == nsAttrValue::eInteger;
int32_t start = 0;
if (haveStart) {
start = startAttr->GetIntegerValue() - 1;
}
bool haveReversed = !!aAttributes->GetAttr(nsGkAtoms::reversed);
bool haveReversed = !!aBuilder.GetAttr(nsGkAtoms::reversed);
if (haveReversed) {
if (haveStart) {
start += 2; // i.e. the attr value + 1
@ -97,11 +96,11 @@ void HTMLSharedListElement::MapOLAttributesIntoRule(
}
}
if (haveStart || haveReversed) {
aDecls.SetCounterResetListItem(start, haveReversed);
aBuilder.SetCounterResetListItem(start, haveReversed);
}
}
HTMLSharedListElement::MapAttributesIntoRule(aAttributes, aDecls);
HTMLSharedListElement::MapAttributesIntoRule(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -22,14 +22,13 @@ class HTMLSharedListElement final : public nsGenericHTMLElement {
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
bool Reversed() const { return GetBoolAttr(nsGkAtoms::reversed); }
void SetReversed(bool aReversed, mozilla::ErrorResult& rv) {
@ -55,10 +54,8 @@ class HTMLSharedListElement final : public nsGenericHTMLElement {
JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapOLAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
static void MapOLAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -16,10 +16,10 @@
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/AttributeStyles.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/Preferences.h"
#include "nsGkAtoms.h"
#include "nsMappedAttributes.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Source)
@ -178,6 +178,12 @@ JSObject* HTMLSourceElement::WrapNode(JSContext* aCx,
return HTMLSourceElement_Binding::Wrap(aCx, this, aGivenProto);
}
/**
* Helper to map the image source attributes.
* Note: This will override the declaration created by the presentation
* attributes of HTMLImageElement (i.e. mapped by MapImageSizeAttributeInto).
* https://html.spec.whatwg.org/multipage/embedded-content.html#the-source-element
*/
void HTMLSourceElement::BuildMappedAttributesForImage() {
MOZ_ASSERT(NS_IsMainThread());
@ -191,10 +197,6 @@ void HTMLSourceElement::BuildMappedAttributesForImage() {
if (!document) {
return;
}
AttributeStyles* attrStyles = document->GetAttributeStyles();
if (!attrStyles) {
return;
}
const nsAttrValue* width = mAttrs.GetAttr(nsGkAtoms::width);
const nsAttrValue* height = mAttrs.GetAttr(nsGkAtoms::height);
@ -202,36 +204,33 @@ void HTMLSourceElement::BuildMappedAttributesForImage() {
return;
}
const size_t count = (width ? 1 : 0) + (height ? 1 : 0);
RefPtr<nsMappedAttributes> modifiableMapped(new (count) nsMappedAttributes(
attrStyles, nsGenericHTMLElement::MapPictureSourceSizeAttributesInto));
MOZ_ASSERT(modifiableMapped);
auto maybeSetAttr = [&](nsAtom* aName, const nsAttrValue* aValue) {
if (!aValue) {
return;
}
nsAttrValue val(*aValue);
bool oldValueSet = false;
modifiableMapped->SetAndSwapAttr(aName, val, &oldValueSet);
};
maybeSetAttr(nsGkAtoms::width, width);
maybeSetAttr(nsGkAtoms::height, height);
RefPtr<nsMappedAttributes> newAttrs =
attrStyles->UniqueMappedAttributes(modifiableMapped);
NS_ENSURE_TRUE_VOID(newAttrs);
if (newAttrs != modifiableMapped) {
// Reset the stylesheet of modifiableMapped so that it doesn't spend time
// trying to remove itself from the hash. There is no risk that
// modifiableMapped is in the hash since we created it ourselves and it
// didn't come from the stylesheet (in which case it would not have been
// modifiable).
modifiableMapped->DropAttributeStylesReference();
MappedDeclarationsBuilder builder(*this, *document);
// We should set the missing property values with auto value to make sure it
// overrides the declaration created by the presentation attributes of
// HTMLImageElement. This can make sure we compute the ratio-dependent axis
// size properly by the natural aspect-ratio of the image.
//
// Note: The spec doesn't specify this, so we follow the implementation in
// other browsers.
// Spec issue: https://github.com/whatwg/html/issues/8178.
if (width) {
MapDimensionAttributeInto(builder, eCSSProperty_width, *width);
} else {
builder.SetAutoValue(eCSSProperty_width);
}
mMappedAttributesForImage = std::move(newAttrs);
if (height) {
MapDimensionAttributeInto(builder, eCSSProperty_height, *height);
} else {
builder.SetAutoValue(eCSSProperty_height);
}
if (width && height) {
DoMapAspectRatio(*width, *height, builder);
} else {
builder.SetAutoValue(eCSSProperty_aspect_ratio);
}
mMappedAttributesForImage = builder.TakeDeclarationBlock();
}
} // namespace mozilla::dom

View File

@ -103,7 +103,7 @@ class HTMLSourceElement final : public nsGenericHTMLElement {
SetUnsignedIntAttr(nsGkAtoms::height, aHeight, 0, aRv);
}
const nsMappedAttributes* GetAttributesMappedForImage() const {
const StyleLockedDeclarationBlock* GetAttributesMappedForImage() const {
return mMappedAttributesForImage;
}
@ -149,7 +149,7 @@ class HTMLSourceElement final : public nsGenericHTMLElement {
// The mapped attributes to HTMLImageElement if we are associated with a
// <picture> with a valid <img>.
RefPtr<nsMappedAttributes> mMappedAttributesForImage;
RefPtr<StyleLockedDeclarationBlock> mMappedAttributesForImage;
};
} // namespace mozilla::dom

View File

@ -7,11 +7,6 @@
#include "mozilla/dom/HTMLSpanElement.h"
#include "mozilla/dom/HTMLSpanElementBinding.h"
#include "mozilla/MappedDeclarations.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsAtom.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Span)
namespace mozilla::dom {

View File

@ -6,9 +6,8 @@
#include "mozilla/dom/HTMLTableCaptionElement.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsAttrValueInlines.h"
#include "nsMappedAttributes.h"
#include "nsStyleConsts.h"
#include "mozilla/dom/HTMLTableCaptionElementBinding.h"
@ -42,14 +41,15 @@ bool HTMLTableCaptionElement::ParseAttribute(
}
void HTMLTableCaptionElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty_caption_side)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
if (value && value->Type() == nsAttrValue::eEnum)
aDecls.SetKeywordValue(eCSSProperty_caption_side, value->GetEnumValue());
MappedDeclarationsBuilder& aBuilder) {
if (!aBuilder.PropertyIsSet(eCSSProperty_caption_side)) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::align);
if (value && value->Type() == nsAttrValue::eEnum) {
aBuilder.SetKeywordValue(eCSSProperty_caption_side,
value->GetEnumValue());
}
}
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -24,25 +24,22 @@ class HTMLTableCaptionElement final : public nsGenericHTMLElement {
SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
}
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
protected:
virtual ~HTMLTableCaptionElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -8,8 +8,7 @@
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLTableElement.h"
#include "mozilla/dom/HTMLTableRowElement.h"
#include "mozilla/MappedDeclarations.h"
#include "nsMappedAttributes.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsAttrValueInlines.h"
#include "celldata.h"
#include "mozilla/dom/HTMLTableCellElementBinding.h"
@ -84,12 +83,11 @@ int32_t HTMLTableCellElement::CellIndex() const {
return -1;
}
nsMappedAttributes*
StyleLockedDeclarationBlock*
HTMLTableCellElement::GetMappedAttributesInheritedFromTable() const {
if (HTMLTableElement* table = GetTable()) {
return table->GetAttributesMappedForCell();
}
return nullptr;
}
@ -162,27 +160,27 @@ bool HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID,
}
void HTMLTableCellElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MapImageSizeAttributesInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
MapImageSizeAttributesInto(aBuilder);
if (!aDecls.PropertyIsSet(eCSSProperty_white_space)) {
if (!aBuilder.PropertyIsSet(eCSSProperty_white_space)) {
// nowrap: enum
if (aAttributes->GetAttr(nsGkAtoms::nowrap)) {
if (aBuilder.GetAttr(nsGkAtoms::nowrap)) {
// See if our width is not a nonzero integer width.
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
nsCompatibility mode = aDecls.Document()->GetCompatibilityMode();
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::width);
nsCompatibility mode = aBuilder.Document().GetCompatibilityMode();
if (!value || value->Type() != nsAttrValue::eInteger ||
value->GetIntegerValue() == 0 || eCompatibility_NavQuirks != mode) {
aDecls.SetKeywordValue(eCSSProperty_white_space,
StyleWhiteSpace::Nowrap);
aBuilder.SetKeywordValue(eCSSProperty_white_space,
StyleWhiteSpace::Nowrap);
}
}
}
nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapDivAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapVAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapBackgroundAttributesInto(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -96,31 +96,28 @@ class HTMLTableCellElement final : public nsGenericHTMLElement {
SetHTMLAttr(nsGkAtoms::bgcolor, aBgColor, aError);
}
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
// Get mapped attributes of ancestor table, if any
nsMappedAttributes* GetMappedAttributesInheritedFromTable() const;
StyleLockedDeclarationBlock* GetMappedAttributesInheritedFromTable() const;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
protected:
virtual ~HTMLTableCellElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
HTMLTableElement* GetTable() const;
HTMLTableRowElement* GetRow() const;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -6,9 +6,8 @@
#include "mozilla/dom/HTMLTableColElement.h"
#include "mozilla/dom/HTMLTableColElementBinding.h"
#include "nsMappedAttributes.h"
#include "nsAttrValueInlines.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(TableCol)
@ -58,25 +57,25 @@ bool HTMLTableColElement::ParseAttribute(int32_t aNamespaceID,
}
void HTMLTableColElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty__x_span)) {
MappedDeclarationsBuilder& aBuilder) {
if (!aBuilder.PropertyIsSet(eCSSProperty__x_span)) {
// span: int
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::span);
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::span);
if (value && value->Type() == nsAttrValue::eInteger) {
int32_t val = value->GetIntegerValue();
// Note: Do NOT use this code for table cells! The value "0"
// means something special for colspan and rowspan, but for <col
// span> and <colgroup span> it's just disallowed.
if (val > 0) {
aDecls.SetIntValue(eCSSProperty__x_span, value->GetIntegerValue());
aBuilder.SetIntValue(eCSSProperty__x_span, value->GetIntegerValue());
}
}
}
nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapWidthAttributeInto(aBuilder);
nsGenericHTMLElement::MapDivAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapVAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -47,24 +47,22 @@ class HTMLTableColElement final : public nsGenericHTMLElement {
SetHTMLAttr(nsGkAtoms::width, aWidth, aError);
}
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
protected:
virtual ~HTMLTableColElement();
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -6,9 +6,9 @@
#include "mozilla/dom/HTMLTableElement.h"
#include "mozilla/AttributeStyles.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/DeclarationBlock.h"
#include "nsAttrValueInlines.h"
#include "nsMappedAttributes.h"
#include "nsWrapperCacheInlines.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLCollectionBinding.h"
@ -499,8 +499,7 @@ void TableRowsCollection::NodeWillBeDestroyed(nsINode* aNode) {
HTMLTableElement::HTMLTableElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: nsGenericHTMLElement(std::move(aNodeInfo)),
mTableInheritedAttributes(nullptr) {
: nsGenericHTMLElement(std::move(aNodeInfo)) {
SetHasWeirdParserInsertionMode();
}
@ -840,7 +839,7 @@ bool HTMLTableElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLTableElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MappedDeclarationsBuilder& aBuilder) {
// XXX Bug 211636: This function is used by a single style rule
// that's used to match two different type of elements -- tables, and
// table cells. (nsHTMLTableCellElement overrides
@ -852,56 +851,55 @@ void HTMLTableElement::MapAttributesIntoRule(
// when the display type is changed).
// cellspacing
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellspacing);
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::cellspacing);
if (value && value->Type() == nsAttrValue::eInteger &&
!aDecls.PropertyIsSet(eCSSProperty_border_spacing)) {
aDecls.SetPixelValue(eCSSProperty_border_spacing,
float(value->GetIntegerValue()));
!aBuilder.PropertyIsSet(eCSSProperty_border_spacing)) {
aBuilder.SetPixelValue(eCSSProperty_border_spacing,
float(value->GetIntegerValue()));
}
// align; Check for enumerated type (it may be another type if
// illegal)
value = aAttributes->GetAttr(nsGkAtoms::align);
value = aBuilder.GetAttr(nsGkAtoms::align);
if (value && value->Type() == nsAttrValue::eEnum) {
if (value->GetEnumValue() == uint8_t(StyleTextAlign::Center) ||
value->GetEnumValue() == uint8_t(StyleTextAlign::MozCenter)) {
aDecls.SetAutoValueIfUnset(eCSSProperty_margin_left);
aDecls.SetAutoValueIfUnset(eCSSProperty_margin_right);
aBuilder.SetAutoValueIfUnset(eCSSProperty_margin_left);
aBuilder.SetAutoValueIfUnset(eCSSProperty_margin_right);
}
}
// bordercolor
value = aAttributes->GetAttr(nsGkAtoms::bordercolor);
value = aBuilder.GetAttr(nsGkAtoms::bordercolor);
nscolor color;
if (value && value->GetColorValue(color)) {
aDecls.SetColorValueIfUnset(eCSSProperty_border_top_color, color);
aDecls.SetColorValueIfUnset(eCSSProperty_border_left_color, color);
aDecls.SetColorValueIfUnset(eCSSProperty_border_bottom_color, color);
aDecls.SetColorValueIfUnset(eCSSProperty_border_right_color, color);
aBuilder.SetColorValueIfUnset(eCSSProperty_border_top_color, color);
aBuilder.SetColorValueIfUnset(eCSSProperty_border_left_color, color);
aBuilder.SetColorValueIfUnset(eCSSProperty_border_bottom_color, color);
aBuilder.SetColorValueIfUnset(eCSSProperty_border_right_color, color);
}
// border
const nsAttrValue* borderValue = aAttributes->GetAttr(nsGkAtoms::border);
if (borderValue) {
if (const nsAttrValue* borderValue = aBuilder.GetAttr(nsGkAtoms::border)) {
// border = 1 pixel default
int32_t borderThickness = 1;
if (borderValue->Type() == nsAttrValue::eInteger)
if (borderValue->Type() == nsAttrValue::eInteger) {
borderThickness = borderValue->GetIntegerValue();
}
// by default, set all border sides to the specified width
aDecls.SetPixelValueIfUnset(eCSSProperty_border_top_width,
(float)borderThickness);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_left_width,
(float)borderThickness);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_bottom_width,
(float)borderThickness);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_right_width,
(float)borderThickness);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_top_width,
(float)borderThickness);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_left_width,
(float)borderThickness);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_bottom_width,
(float)borderThickness);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_right_width,
(float)borderThickness);
}
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapImageSizeAttributesInto(aBuilder);
nsGenericHTMLElement::MapBackgroundAttributesInto(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)
@ -929,66 +927,30 @@ nsMapRuleToAttributesFunc HTMLTableElement::GetAttributeMappingFunction()
return &MapAttributesIntoRule;
}
static void MapInheritedTableAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellpadding);
if (value && value->Type() == nsAttrValue::eInteger) {
// We have cellpadding. This will override our padding values if we
// don't have any set.
float pad = float(value->GetIntegerValue());
aDecls.SetPixelValueIfUnset(eCSSProperty_padding_top, pad);
aDecls.SetPixelValueIfUnset(eCSSProperty_padding_right, pad);
aDecls.SetPixelValueIfUnset(eCSSProperty_padding_bottom, pad);
aDecls.SetPixelValueIfUnset(eCSSProperty_padding_left, pad);
}
}
nsMappedAttributes* HTMLTableElement::GetAttributesMappedForCell() {
return mTableInheritedAttributes;
}
void HTMLTableElement::BuildInheritedAttributes() {
NS_ASSERTION(!mTableInheritedAttributes,
"potential leak, plus waste of work");
MOZ_ASSERT(!mTableInheritedAttributes, "potential leak, plus waste of work");
MOZ_ASSERT(NS_IsMainThread());
Document* document = GetComposedDoc();
if (!document) {
return;
}
AttributeStyles* attrStyles = document->GetAttributeStyles();
if (!attrStyles) {
const nsAttrValue* value = GetParsedAttr(nsGkAtoms::cellpadding);
if (!value) {
return;
}
RefPtr<nsMappedAttributes> newAttrs;
if (const nsAttrValue* value = mAttrs.GetAttr(nsGkAtoms::cellpadding)) {
RefPtr<nsMappedAttributes> modifiableMapped =
new nsMappedAttributes(attrStyles, MapInheritedTableAttributesIntoRule);
if (modifiableMapped) {
nsAttrValue val(*value);
bool oldValueSet;
modifiableMapped->SetAndSwapAttr(nsGkAtoms::cellpadding, val,
&oldValueSet);
}
newAttrs = attrStyles->UniqueMappedAttributes(modifiableMapped);
NS_ASSERTION(newAttrs, "out of memory, but handling gracefully");
if (newAttrs != modifiableMapped) {
// Reset the stylesheet of modifiableMapped so that it doesn't spend time
// trying to remove itself from the hash. There is no risk that
// modifiableMapped is in the hash since we created it ourselves and it
// didn't come from the attrStyles (in which case it would not have been
// modifiable).
modifiableMapped->DropAttributeStylesReference();
}
}
mTableInheritedAttributes = newAttrs;
NS_IF_ADDREF(mTableInheritedAttributes);
// We have cellpadding. This will override our padding values if we don't
// have any set.
float pad = float(value->GetIntegerValue());
MappedDeclarationsBuilder builder(*this, *document);
builder.SetPixelValue(eCSSProperty_padding_top, pad);
builder.SetPixelValue(eCSSProperty_padding_right, pad);
builder.SetPixelValue(eCSSProperty_padding_bottom, pad);
builder.SetPixelValue(eCSSProperty_padding_left, pad);
mTableInheritedAttributes = builder.TakeDeclarationBlock();
}
void HTMLTableElement::ReleaseInheritedAttributes() {
NS_IF_RELEASE(mTableInheritedAttributes);
mTableInheritedAttributes = nullptr;
}
nsresult HTMLTableElement::BindToTree(BindContext& aContext, nsINode& aParent) {

View File

@ -171,7 +171,9 @@ class HTMLTableElement final : public nsGenericHTMLElement {
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTableElement,
nsGenericHTMLElement)
nsMappedAttributes* GetAttributesMappedForCell();
StyleLockedDeclarationBlock* GetAttributesMappedForCell() const {
return mTableInheritedAttributes;
}
protected:
virtual ~HTMLTableElement();
@ -190,13 +192,12 @@ class HTMLTableElement final : public nsGenericHTMLElement {
RefPtr<nsContentList> mTBodies;
RefPtr<TableRowsCollection> mRows;
nsMappedAttributes* mTableInheritedAttributes;
RefPtr<StyleLockedDeclarationBlock> mTableInheritedAttributes;
void BuildInheritedAttributes();
void ReleaseInheritedAttributes();
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -6,8 +6,7 @@
#include "mozilla/dom/HTMLTableRowElement.h"
#include "mozilla/dom/HTMLTableElement.h"
#include "mozilla/MappedDeclarations.h"
#include "nsMappedAttributes.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsAttrValueInlines.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/HTMLTableRowElementBinding.h"
@ -220,12 +219,12 @@ bool HTMLTableRowElement::ParseAttribute(int32_t aNamespaceID,
}
void HTMLTableRowElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
nsGenericHTMLElement::MapHeightAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
nsGenericHTMLElement::MapHeightAttributeInto(aBuilder);
nsGenericHTMLElement::MapDivAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapVAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapBackgroundAttributesInto(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -84,8 +84,7 @@ class HTMLTableRowElement final : public nsGenericHTMLElement {
RefPtr<nsContentList> mCells;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -5,8 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/HTMLTableSectionElement.h"
#include "mozilla/MappedDeclarations.h"
#include "nsMappedAttributes.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "nsAttrValueInlines.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/HTMLTableSectionElementBinding.h"
@ -141,18 +140,19 @@ bool HTMLTableSectionElement::ParseAttribute(
}
void HTMLTableSectionElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MappedDeclarationsBuilder& aBuilder) {
// height: value
if (!aDecls.PropertyIsSet(eCSSProperty_height)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
if (value && value->Type() == nsAttrValue::eInteger)
aDecls.SetPixelValue(eCSSProperty_height,
(float)value->GetIntegerValue());
if (!aBuilder.PropertyIsSet(eCSSProperty_height)) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::height);
if (value && value->Type() == nsAttrValue::eInteger) {
aBuilder.SetPixelValue(eCSSProperty_height,
(float)value->GetIntegerValue());
}
}
nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aDecls);
nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
nsGenericHTMLElement::MapDivAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapVAlignAttributeInto(aBuilder);
nsGenericHTMLElement::MapBackgroundAttributesInto(aBuilder);
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -47,12 +47,11 @@ class HTMLTableSectionElement final : public nsGenericHTMLElement {
SetHTMLAttr(nsGkAtoms::valign, aVAlign, aError);
}
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
const override;
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult) override;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
@ -68,8 +67,7 @@ class HTMLTableSectionElement final : public nsGenericHTMLElement {
RefPtr<nsContentList> mRows;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace mozilla::dom

View File

@ -8,7 +8,6 @@
#include "mozilla/dom/HTMLTemplateElementBinding.h"
#include "mozilla/dom/Document.h"
#include "mozilla/MappedDeclarations.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsAtom.h"

View File

@ -13,7 +13,7 @@
#include "mozilla/dom/HTMLTextAreaElementBinding.h"
#include "mozilla/dom/MutationEventBinding.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/PresState.h"
#include "mozilla/TextControlState.h"
@ -32,8 +32,6 @@
#include "nsITextControlFrame.h"
#include "nsLayoutUtils.h"
#include "nsLinebreakConverter.h"
#include "nsMappedAttributes.h"
#include "nsPIDOMWindow.h"
#include "nsPresContext.h"
#include "nsReadableUtils.h"
#include "nsStyleConsts.h"
@ -378,20 +376,18 @@ bool HTMLTextAreaElement::ParseAttribute(int32_t aNamespaceID,
}
void HTMLTextAreaElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MappedDeclarationsBuilder& aBuilder) {
// wrap=off
if (!aDecls.PropertyIsSet(eCSSProperty_white_space)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::wrap);
if (!aBuilder.PropertyIsSet(eCSSProperty_white_space)) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::wrap);
if (value && value->Type() == nsAttrValue::eString &&
value->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
aDecls.SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Pre);
aBuilder.SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Pre);
}
}
nsGenericHTMLFormControlElementWithState::MapDivAlignAttributeInto(
aAttributes, aDecls);
nsGenericHTMLFormControlElementWithState::MapCommonAttributesInto(aAttributes,
aDecls);
nsGenericHTMLFormControlElementWithState::MapDivAlignAttributeInto(aBuilder);
nsGenericHTMLFormControlElementWithState::MapCommonAttributesInto(aBuilder);
}
nsChangeHint HTMLTextAreaElement::GetAttributeChangeHint(

View File

@ -399,8 +399,7 @@ class HTMLTextAreaElement final : public TextControlElement,
ErrorResult& aRv);
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
};
} // namespace dom

View File

@ -27,7 +27,6 @@
#include "nsIScriptError.h"
#include "nsISupportsImpl.h"
#include "nsISupportsPrimitives.h"
#include "nsMappedAttributes.h"
#include "nsNetUtil.h"
#include "nsStyleConsts.h"
#include "nsThreadUtils.h"

View File

@ -168,10 +168,9 @@ bool HTMLVideoElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
}
void HTMLVideoElement::MapAttributesIntoRule(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls,
MapAspectRatio::Yes);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
MapImageSizeAttributesInto(aBuilder, MapAspectRatio::Yes);
MapCommonAttributesInto(aBuilder);
}
NS_IMETHODIMP_(bool)

View File

@ -191,8 +191,7 @@ class HTMLVideoElement final : public HTMLMediaElement {
// SetVisualCloneTarget() instead.
RefPtr<HTMLVideoElement> mVisualCloneSource;
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
MappedDeclarations&);
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
static bool IsVideoStatsEnabled();
double TotalPlayTime() const;

View File

@ -11,7 +11,7 @@
#include "mozilla/HTMLEditor.h"
#include "mozilla/IMEContentObserver.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/Maybe.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/PresShell.h"
@ -28,7 +28,6 @@
#include "nsQueryObject.h"
#include "mozilla/dom/BindContext.h"
#include "mozilla/dom/Document.h"
#include "nsMappedAttributes.h"
#include "nsPIDOMWindow.h"
#include "nsIFrameInlines.h"
#include "nsIScrollableFrame.h"
@ -1266,26 +1265,25 @@ bool nsGenericHTMLElement::ParseScrollingValue(const nsAString& aString,
return aResult.ParseEnumValue(aString, kScrollingTable, false);
}
static inline void MapLangAttributeInto(const nsMappedAttributes* aAttributes,
MappedDeclarations& aDecls) {
const nsAttrValue* langValue = aAttributes->GetAttr(nsGkAtoms::lang);
static inline void MapLangAttributeInto(MappedDeclarationsBuilder& aBuilder) {
const nsAttrValue* langValue = aBuilder.GetAttr(nsGkAtoms::lang);
if (!langValue) {
return;
}
MOZ_ASSERT(langValue->Type() == nsAttrValue::eAtom);
aDecls.SetIdentAtomValueIfUnset(eCSSProperty__x_lang,
langValue->GetAtomValue());
if (!aDecls.PropertyIsSet(eCSSProperty_text_emphasis_position)) {
aBuilder.SetIdentAtomValueIfUnset(eCSSProperty__x_lang,
langValue->GetAtomValue());
if (!aBuilder.PropertyIsSet(eCSSProperty_text_emphasis_position)) {
const nsAtom* lang = langValue->GetAtomValue();
if (nsStyleUtil::MatchesLanguagePrefix(lang, u"zh")) {
aDecls.SetKeywordValue(eCSSProperty_text_emphasis_position,
StyleTextEmphasisPosition::UNDER.bits);
aBuilder.SetKeywordValue(eCSSProperty_text_emphasis_position,
StyleTextEmphasisPosition::UNDER.bits);
} else if (nsStyleUtil::MatchesLanguagePrefix(lang, u"ja") ||
nsStyleUtil::MatchesLanguagePrefix(lang, u"mn")) {
// This branch is currently no part of the spec.
// See bug 1040668 comment 69 and comment 75.
aDecls.SetKeywordValue(eCSSProperty_text_emphasis_position,
StyleTextEmphasisPosition::OVER.bits);
aBuilder.SetKeywordValue(eCSSProperty_text_emphasis_position,
StyleTextEmphasisPosition::OVER.bits);
}
}
}
@ -1294,31 +1292,30 @@ static inline void MapLangAttributeInto(const nsMappedAttributes* aAttributes,
* Handle attributes common to all html elements
*/
void nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty__moz_user_modify)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::contenteditable);
MappedDeclarationsBuilder& aBuilder) {
if (!aBuilder.PropertyIsSet(eCSSProperty__moz_user_modify)) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::contenteditable);
if (value) {
if (value->Equals(nsGkAtoms::_empty, eCaseMatters) ||
value->Equals(nsGkAtoms::_true, eIgnoreCase)) {
aDecls.SetKeywordValue(eCSSProperty__moz_user_modify,
StyleUserModify::ReadWrite);
aBuilder.SetKeywordValue(eCSSProperty__moz_user_modify,
StyleUserModify::ReadWrite);
} else if (value->Equals(nsGkAtoms::_false, eIgnoreCase)) {
aDecls.SetKeywordValue(eCSSProperty__moz_user_modify,
StyleUserModify::ReadOnly);
aBuilder.SetKeywordValue(eCSSProperty__moz_user_modify,
StyleUserModify::ReadOnly);
}
}
}
MapLangAttributeInto(aAttributes, aDecls);
MapLangAttributeInto(aBuilder);
}
void nsGenericHTMLElement::MapCommonAttributesInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MapCommonAttributesIntoExceptHidden(aAttributes, aDecls);
if (!aDecls.PropertyIsSet(eCSSProperty_display)) {
if (aAttributes->IndexOfAttr(nsGkAtoms::hidden) >= 0) {
aDecls.SetKeywordValue(eCSSProperty_display, StyleDisplay::None);
MappedDeclarationsBuilder& aBuilder) {
MapCommonAttributesIntoExceptHidden(aBuilder);
if (!aBuilder.PropertyIsSet(eCSSProperty_display)) {
if (aBuilder.GetAttr(nsGkAtoms::hidden)) {
aBuilder.SetKeywordValue(eCSSProperty_display, StyleDisplay::None);
}
}
}
@ -1364,24 +1361,24 @@ const Element::MappedAttributeEntry
{nsGkAtoms::bgcolor}, {nullptr}};
void nsGenericHTMLElement::MapImageAlignAttributeInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
MappedDeclarationsBuilder& aBuilder) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::align);
if (value && value->Type() == nsAttrValue::eEnum) {
int32_t align = value->GetEnumValue();
if (!aDecls.PropertyIsSet(eCSSProperty_float)) {
if (!aBuilder.PropertyIsSet(eCSSProperty_float)) {
if (align == uint8_t(StyleTextAlign::Left)) {
aDecls.SetKeywordValue(eCSSProperty_float, StyleFloat::Left);
aBuilder.SetKeywordValue(eCSSProperty_float, StyleFloat::Left);
} else if (align == uint8_t(StyleTextAlign::Right)) {
aDecls.SetKeywordValue(eCSSProperty_float, StyleFloat::Right);
aBuilder.SetKeywordValue(eCSSProperty_float, StyleFloat::Right);
}
}
if (!aDecls.PropertyIsSet(eCSSProperty_vertical_align)) {
if (!aBuilder.PropertyIsSet(eCSSProperty_vertical_align)) {
switch (align) {
case uint8_t(StyleTextAlign::Left):
case uint8_t(StyleTextAlign::Right):
break;
default:
aDecls.SetKeywordValue(eCSSProperty_vertical_align, align);
aBuilder.SetKeywordValue(eCSSProperty_vertical_align, align);
break;
}
}
@ -1389,78 +1386,74 @@ void nsGenericHTMLElement::MapImageAlignAttributeInto(
}
void nsGenericHTMLElement::MapDivAlignAttributeInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty_text_align)) {
MappedDeclarationsBuilder& aBuilder) {
if (!aBuilder.PropertyIsSet(eCSSProperty_text_align)) {
// align: enum
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::align);
if (value && value->Type() == nsAttrValue::eEnum)
aDecls.SetKeywordValue(eCSSProperty_text_align, value->GetEnumValue());
aBuilder.SetKeywordValue(eCSSProperty_text_align, value->GetEnumValue());
}
}
void nsGenericHTMLElement::MapVAlignAttributeInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty_vertical_align)) {
MappedDeclarationsBuilder& aBuilder) {
if (!aBuilder.PropertyIsSet(eCSSProperty_vertical_align)) {
// align: enum
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign);
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::valign);
if (value && value->Type() == nsAttrValue::eEnum)
aDecls.SetKeywordValue(eCSSProperty_vertical_align,
value->GetEnumValue());
aBuilder.SetKeywordValue(eCSSProperty_vertical_align,
value->GetEnumValue());
}
}
static void MapDimensionAttributeInto(MappedDeclarations& aDecls,
nsCSSPropertyID aProp,
const nsAttrValue& aValue) {
MOZ_ASSERT(!aDecls.PropertyIsSet(aProp),
void nsGenericHTMLElement::MapDimensionAttributeInto(
MappedDeclarationsBuilder& aBuilder, nsCSSPropertyID aProp,
const nsAttrValue& aValue) {
MOZ_ASSERT(!aBuilder.PropertyIsSet(aProp),
"Why mapping the same property twice?");
if (aValue.Type() == nsAttrValue::eInteger) {
return aDecls.SetPixelValue(aProp, aValue.GetIntegerValue());
return aBuilder.SetPixelValue(aProp, aValue.GetIntegerValue());
}
if (aValue.Type() == nsAttrValue::ePercent) {
return aDecls.SetPercentValue(aProp, aValue.GetPercentValue());
return aBuilder.SetPercentValue(aProp, aValue.GetPercentValue());
}
if (aValue.Type() == nsAttrValue::eDoubleValue) {
return aDecls.SetPixelValue(aProp, aValue.GetDoubleValue());
return aBuilder.SetPixelValue(aProp, aValue.GetDoubleValue());
}
}
void nsGenericHTMLElement::MapImageMarginAttributeInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
const nsAttrValue* value;
MappedDeclarationsBuilder& aBuilder) {
// hspace: value
value = aAttributes->GetAttr(nsGkAtoms::hspace);
if (value) {
MapDimensionAttributeInto(aDecls, eCSSProperty_margin_left, *value);
MapDimensionAttributeInto(aDecls, eCSSProperty_margin_right, *value);
if (const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::hspace)) {
MapDimensionAttributeInto(aBuilder, eCSSProperty_margin_left, *value);
MapDimensionAttributeInto(aBuilder, eCSSProperty_margin_right, *value);
}
// vspace: value
value = aAttributes->GetAttr(nsGkAtoms::vspace);
if (value) {
MapDimensionAttributeInto(aDecls, eCSSProperty_margin_top, *value);
MapDimensionAttributeInto(aDecls, eCSSProperty_margin_bottom, *value);
if (const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::vspace)) {
MapDimensionAttributeInto(aBuilder, eCSSProperty_margin_top, *value);
MapDimensionAttributeInto(aBuilder, eCSSProperty_margin_bottom, *value);
}
}
void nsGenericHTMLElement::MapWidthAttributeInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width)) {
MapDimensionAttributeInto(aDecls, eCSSProperty_width, *value);
MappedDeclarationsBuilder& aBuilder) {
if (const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::width)) {
MapDimensionAttributeInto(aBuilder, eCSSProperty_width, *value);
}
}
void nsGenericHTMLElement::MapHeightAttributeInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height)) {
MapDimensionAttributeInto(aDecls, eCSSProperty_height, *value);
MappedDeclarationsBuilder& aBuilder) {
if (const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::height)) {
MapDimensionAttributeInto(aBuilder, eCSSProperty_height, *value);
}
}
static void DoMapAspectRatio(const nsAttrValue& aWidth,
const nsAttrValue& aHeight,
MappedDeclarations& aDecls) {
void nsGenericHTMLElement::DoMapAspectRatio(
const nsAttrValue& aWidth, const nsAttrValue& aHeight,
MappedDeclarationsBuilder& aBuilder) {
Maybe<double> w;
if (aWidth.Type() == nsAttrValue::eInteger) {
w.emplace(aWidth.GetIntegerValue());
@ -1476,126 +1469,88 @@ static void DoMapAspectRatio(const nsAttrValue& aWidth,
}
if (w && h) {
aDecls.SetAspectRatio(*w, *h);
aBuilder.SetAspectRatio(*w, *h);
}
}
void nsGenericHTMLElement::MapImageSizeAttributesInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls,
MapAspectRatio aMapAspectRatio) {
auto* width = aAttributes->GetAttr(nsGkAtoms::width);
auto* height = aAttributes->GetAttr(nsGkAtoms::height);
MappedDeclarationsBuilder& aBuilder, MapAspectRatio aMapAspectRatio) {
auto* width = aBuilder.GetAttr(nsGkAtoms::width);
auto* height = aBuilder.GetAttr(nsGkAtoms::height);
if (width) {
MapDimensionAttributeInto(aDecls, eCSSProperty_width, *width);
MapDimensionAttributeInto(aBuilder, eCSSProperty_width, *width);
}
if (height) {
MapDimensionAttributeInto(aDecls, eCSSProperty_height, *height);
MapDimensionAttributeInto(aBuilder, eCSSProperty_height, *height);
}
if (aMapAspectRatio == MapAspectRatio::Yes && width && height) {
DoMapAspectRatio(*width, *height, aDecls);
}
}
void nsGenericHTMLElement::MapPictureSourceSizeAttributesInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
const auto* width = aAttributes->GetAttr(nsGkAtoms::width);
const auto* height = aAttributes->GetAttr(nsGkAtoms::height);
if (!width && !height) {
return;
}
// We should set the missing property values with auto value to make sure it
// overrides the declaraion created by the presentation attributes of
// HTMLImageElement. This can make sure we compute the ratio-dependent axis
// size properly by the natural aspect-ratio of the image.
//
// Note: The spec doesn't specify this, so we follow the implementation in
// other browsers.
// Spec issue: https://github.com/whatwg/html/issues/8178.
if (width) {
MapDimensionAttributeInto(aDecls, eCSSProperty_width, *width);
} else {
aDecls.SetAutoValue(eCSSProperty_width);
}
if (height) {
MapDimensionAttributeInto(aDecls, eCSSProperty_height, *height);
} else {
aDecls.SetAutoValue(eCSSProperty_height);
}
if (width && height) {
DoMapAspectRatio(*width, *height, aDecls);
} else {
aDecls.SetAutoValue(eCSSProperty_aspect_ratio);
DoMapAspectRatio(*width, *height, aBuilder);
}
}
void nsGenericHTMLElement::MapAspectRatioInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
auto* width = aAttributes->GetAttr(nsGkAtoms::width);
auto* height = aAttributes->GetAttr(nsGkAtoms::height);
MappedDeclarationsBuilder& aBuilder) {
auto* width = aBuilder.GetAttr(nsGkAtoms::width);
auto* height = aBuilder.GetAttr(nsGkAtoms::height);
if (width && height) {
DoMapAspectRatio(*width, *height, aDecls);
DoMapAspectRatio(*width, *height, aBuilder);
}
}
void nsGenericHTMLElement::MapImageBorderAttributeInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MappedDeclarationsBuilder& aBuilder) {
// border: pixels
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::border);
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::border);
if (!value) return;
nscoord val = 0;
if (value->Type() == nsAttrValue::eInteger) val = value->GetIntegerValue();
aDecls.SetPixelValueIfUnset(eCSSProperty_border_top_width, (float)val);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_right_width, (float)val);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_bottom_width, (float)val);
aDecls.SetPixelValueIfUnset(eCSSProperty_border_left_width, (float)val);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_top_width, (float)val);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_right_width, (float)val);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_bottom_width, (float)val);
aBuilder.SetPixelValueIfUnset(eCSSProperty_border_left_width, (float)val);
aDecls.SetKeywordValueIfUnset(eCSSProperty_border_top_style,
StyleBorderStyle::Solid);
aDecls.SetKeywordValueIfUnset(eCSSProperty_border_right_style,
StyleBorderStyle::Solid);
aDecls.SetKeywordValueIfUnset(eCSSProperty_border_bottom_style,
StyleBorderStyle::Solid);
aDecls.SetKeywordValueIfUnset(eCSSProperty_border_left_style,
StyleBorderStyle::Solid);
aBuilder.SetKeywordValueIfUnset(eCSSProperty_border_top_style,
StyleBorderStyle::Solid);
aBuilder.SetKeywordValueIfUnset(eCSSProperty_border_right_style,
StyleBorderStyle::Solid);
aBuilder.SetKeywordValueIfUnset(eCSSProperty_border_bottom_style,
StyleBorderStyle::Solid);
aBuilder.SetKeywordValueIfUnset(eCSSProperty_border_left_style,
StyleBorderStyle::Solid);
aDecls.SetCurrentColorIfUnset(eCSSProperty_border_top_color);
aDecls.SetCurrentColorIfUnset(eCSSProperty_border_right_color);
aDecls.SetCurrentColorIfUnset(eCSSProperty_border_bottom_color);
aDecls.SetCurrentColorIfUnset(eCSSProperty_border_left_color);
aBuilder.SetCurrentColorIfUnset(eCSSProperty_border_top_color);
aBuilder.SetCurrentColorIfUnset(eCSSProperty_border_right_color);
aBuilder.SetCurrentColorIfUnset(eCSSProperty_border_bottom_color);
aBuilder.SetCurrentColorIfUnset(eCSSProperty_border_left_color);
}
void nsGenericHTMLElement::MapBackgroundInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty_background_image)) {
MappedDeclarationsBuilder& aBuilder) {
if (!aBuilder.PropertyIsSet(eCSSProperty_background_image)) {
// background
nsAttrValue* value =
const_cast<nsAttrValue*>(aAttributes->GetAttr(nsGkAtoms::background));
if (value) {
aDecls.SetBackgroundImage(*value);
if (const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::background)) {
aBuilder.SetBackgroundImage(*value);
}
}
}
void nsGenericHTMLElement::MapBGColorInto(const nsMappedAttributes* aAttributes,
MappedDeclarations& aDecls) {
if (!aDecls.PropertyIsSet(eCSSProperty_background_color)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bgcolor);
nscolor color;
if (value && value->GetColorValue(color)) {
aDecls.SetColorValue(eCSSProperty_background_color, color);
}
void nsGenericHTMLElement::MapBGColorInto(MappedDeclarationsBuilder& aBuilder) {
if (aBuilder.PropertyIsSet(eCSSProperty_background_color)) {
return;
}
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::bgcolor);
nscolor color;
if (value && value->GetColorValue(color)) {
aBuilder.SetColorValue(eCSSProperty_background_color, color);
}
}
void nsGenericHTMLElement::MapBackgroundAttributesInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
MapBackgroundInto(aAttributes, aDecls);
MapBGColorInto(aAttributes, aDecls);
MappedDeclarationsBuilder& aBuilder) {
MapBackgroundInto(aBuilder);
MapBGColorInto(aBuilder);
}
//----------------------------------------------------------------------

View File

@ -8,11 +8,11 @@
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
#include "nsMappedAttributeElement.h"
#include "nsNameSpaceManager.h" // for kNameSpaceID_None
#include "nsIFormControl.h"
#include "nsGkAtoms.h"
#include "nsContentCreatorFunctions.h"
#include "nsStyledElement.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/DOMRect.h"
@ -27,6 +27,8 @@ class nsILayoutHistoryState;
class nsIURI;
struct nsSize;
enum nsCSSPropertyID : int32_t;
namespace mozilla {
class EditorBase;
class ErrorResult;
@ -41,7 +43,7 @@ class HTMLFormElement;
} // namespace dom
} // namespace mozilla
using nsGenericHTMLElementBase = nsMappedAttributeElement;
using nsGenericHTMLElementBase = nsStyledElement;
/**
* A common superclass for HTML elements
@ -495,17 +497,13 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
* @param aData the returned rule data [INOUT]
* @see GetAttributeMappingFunction
*/
static void MapCommonAttributesInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapCommonAttributesInto(mozilla::MappedDeclarationsBuilder&);
/**
* Same as MapCommonAttributesInto except that it does not handle hidden.
*
* @param aAttributes the list of attributes to map
* @param aData the returned rule data [INOUT]
* @see GetAttributeMappingFunction
*/
static void MapCommonAttributesIntoExceptHidden(
const nsMappedAttributes* aAttributes, mozilla::MappedDeclarations&);
mozilla::MappedDeclarationsBuilder&);
static const MappedAttributeEntry sCommonAttributeMap[];
static const MappedAttributeEntry sImageMarginSizeAttributeMap[];
@ -516,46 +514,28 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
static const MappedAttributeEntry sBackgroundColorAttributeMap[];
/**
* Helper to map the align attribute into a style struct.
*
* @param aAttributes the list of attributes to map
* @param aData the returned rule data [INOUT]
* Helper to map the align attribute.
* @see GetAttributeMappingFunction
*/
static void MapImageAlignAttributeInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapImageAlignAttributeInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map the align attribute into a style struct for things
* like <div>, <h1>, etc.
*
* @param aAttributes the list of attributes to map
* @param aData the returned rule data [INOUT]
* Helper to map the align attribute for things like <div>, <h1>, etc.
* @see GetAttributeMappingFunction
*/
static void MapDivAlignAttributeInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapDivAlignAttributeInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map the valign attribute into a style struct for things
* like <col>, <tr>, <section>, etc.
*
* @param aAttributes the list of attributes to map
* @param aData the returned rule data [INOUT]
* Helper to map the valign attribute for things like <col>, <tr>, <section>.
* @see GetAttributeMappingFunction
*/
static void MapVAlignAttributeInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapVAlignAttributeInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map the image border attribute into a style struct.
*
* @param aAttributes the list of attributes to map
* @param aData the returned rule data [INOUT]
* Helper to map the image border attribute.
* @see GetAttributeMappingFunction
*/
static void MapImageBorderAttributeInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapImageBorderAttributeInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map the image margin attribute into a style struct.
*
@ -563,8 +543,21 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
* @param aData the returned rule data [INOUT]
* @see GetAttributeMappingFunction
*/
static void MapImageMarginAttributeInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapImageMarginAttributeInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map a given dimension (width/height) into the declaration
* block, handling percentages and numbers.
*/
static void MapDimensionAttributeInto(mozilla::MappedDeclarationsBuilder&,
nsCSSPropertyID, const nsAttrValue&);
/**
* Maps the aspect ratio given width and height attributes.
*/
static void DoMapAspectRatio(const nsAttrValue& aWidth,
const nsAttrValue& aHeight,
mozilla::MappedDeclarationsBuilder&);
// Whether to map the width and height attributes to aspect-ratio.
enum class MapAspectRatio { No, Yes };
@ -572,18 +565,8 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
/**
* Helper to map the image position attribute into a style struct.
*/
static void MapImageSizeAttributesInto(const nsMappedAttributes*,
mozilla::MappedDeclarations&,
static void MapImageSizeAttributesInto(mozilla::MappedDeclarationsBuilder&,
MapAspectRatio = MapAspectRatio::No);
/**
* Helper to map the iamge source attributes into a style stuct.
* Note:
* This will override the declaration created by the presentation attributes
* of HTMLImageElement (i.e. mapped by MapImageSizeAttributeInto).
* https://html.spec.whatwg.org/multipage/embedded-content.html#the-source-element
*/
static void MapPictureSourceSizeAttributesInto(const nsMappedAttributes*,
mozilla::MappedDeclarations&);
/**
* Helper to map the width and height attributes into the aspect-ratio
@ -594,8 +577,7 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
* MapImageSizeAttributesInto instead, passing MapAspectRatio::Yes instead, as
* that'd be faster.
*/
static void MapAspectRatioInto(const nsMappedAttributes*,
mozilla::MappedDeclarations&);
static void MapAspectRatioInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map `width` attribute into a style struct.
@ -604,57 +586,33 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
* @param aData the returned rule data [INOUT]
* @see GetAttributeMappingFunction
*/
static void MapWidthAttributeInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapWidthAttributeInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map `height` attribute into a style struct.
*
* @param aAttributes the list of attributes to map
* @param aData the returned rule data [INOUT]
* Helper to map `height` attribute.
* @see GetAttributeMappingFunction
*/
static void MapHeightAttributeInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapHeightAttributeInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map the background attribute
* into a style struct.
*
* @param aAttributes the list of attributes to map
* @param aData the returned rule data [INOUT]
* @see GetAttributeMappingFunction
*/
static void MapBackgroundInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapBackgroundInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map the bgcolor attribute
* into a style struct.
*
* @param aAttributes the list of attributes to map
* @param aData the returned rule data [INOUT]
* @see GetAttributeMappingFunction
*/
static void MapBGColorInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapBGColorInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map the background attributes (currently background and bgcolor)
* into a style struct.
*
* @param aAttributes the list of attributes to map
* @param aData the returned rule data [INOUT]
* @see GetAttributeMappingFunction
*/
static void MapBackgroundAttributesInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapBackgroundAttributesInto(mozilla::MappedDeclarationsBuilder&);
/**
* Helper to map the scrolling attribute on FRAME and IFRAME
* into a style struct.
*
* @param aAttributes the list of attributes to map
* @param aData the returned rule data [INOUT]
* Helper to map the scrolling attribute on FRAME and IFRAME.
* @see GetAttributeMappingFunction
*/
static void MapScrollingAttributeInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapScrollingAttributeInto(mozilla::MappedDeclarationsBuilder&);
// Form Helper Routines
/**

View File

@ -17,7 +17,6 @@
#include "nsIContentInlines.h"
#include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
#include "nsCSSValue.h"
#include "nsMappedAttributes.h"
#include "nsStyleConsts.h"
#include "mozilla/dom/Document.h"
#include "nsPresContext.h"
@ -27,7 +26,7 @@
#include "nsIURI.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/MappedDeclarations.h"
#include "mozilla/MappedDeclarationsBuilder.h"
#include "mozilla/dom/MathMLElementBinding.h"
using namespace mozilla;
@ -47,10 +46,10 @@ static nsresult ReportLengthParseError(const nsString& aValue,
}
static nsresult ReportParseErrorNoTag(const nsString& aValue, nsAtom* aAtom,
Document* aDocument) {
Document& aDocument) {
AutoTArray<nsString, 2> argv = {aValue, nsDependentAtomString(aAtom)};
return nsContentUtils::ReportToConsole(
nsIScriptError::errorFlag, "MathML"_ns, aDocument,
nsIScriptError::errorFlag, "MathML"_ns, &aDocument,
nsContentUtils::eMATHML_PROPERTIES, "AttributeParsingErrorNoTag", argv);
}
@ -147,10 +146,10 @@ bool MathMLElement::IsAttributeMapped(const nsAtom* aAttribute) const {
}
nsMapRuleToAttributesFunc MathMLElement::GetAttributeMappingFunction() const {
// It doesn't really matter what our tag is here, because only attributes
// that satisfy IsAttributeMapped will be stored in the mapped attributes
// list and available to the mapping function
return &MapMathMLAttributesInto;
if (mNodeInfo->Equals(nsGkAtoms::mtable_)) {
return &MapMTableAttributesInto;
}
return &MapGlobalMathMLAttributesInto;
}
/* static */
@ -356,8 +355,39 @@ bool MathMLElement::ParseNumericValue(const nsString& aString,
return true;
}
void MathMLElement::MapMathMLAttributesInto(
const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
void MathMLElement::MapMTableAttributesInto(
MappedDeclarationsBuilder& aBuilder) {
// width
//
// "Specifies the desired width of the entire table and is intended for
// visual user agents. When the value is a percentage value, the value is
// relative to the horizontal space a MathML renderer has available for the
// math element. When the value is "auto", the MathML renderer should
// calculate the table width from its contents using whatever layout
// algorithm it chooses. "
//
// values: "auto" | length
// default: auto
//
if (!aBuilder.PropertyIsSet(eCSSProperty_width)) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::width);
nsCSSValue width;
// This does not handle auto and unitless values
if (value && value->Type() == nsAttrValue::eString) {
ParseNumericValue(value->GetStringValue(), width, 0,
&aBuilder.Document());
if (width.GetUnit() == eCSSUnit_Percent) {
aBuilder.SetPercentValue(eCSSProperty_width, width.GetPercentValue());
} else if (width.GetUnit() != eCSSUnit_Null) {
aBuilder.SetLengthValue(eCSSProperty_width, width);
}
}
}
MapGlobalMathMLAttributesInto(aBuilder);
}
void MathMLElement::MapGlobalMathMLAttributesInto(
MappedDeclarationsBuilder& aBuilder) {
// scriptsizemultiplier
//
// "Specifies the multiplier to be used to adjust font size due to changes
@ -366,26 +396,28 @@ void MathMLElement::MapMathMLAttributesInto(
// values: number
// default: 0.71
//
const nsAttrValue* value =
aAttributes->GetAttr(nsGkAtoms::scriptsizemultiplier_);
if (value && value->Type() == nsAttrValue::eString &&
!aDecls.PropertyIsSet(eCSSProperty__moz_script_size_multiplier)) {
aDecls.Document()->WarnOnceAbout(
dom::DeprecatedOperations::
eMathML_DeprecatedScriptsizemultiplierAttribute);
auto str = value->GetStringValue();
str.CompressWhitespace();
// MathML numbers can't have leading '+'
if (str.Length() > 0 && str.CharAt(0) != '+') {
nsresult errorCode;
float floatValue = str.ToFloat(&errorCode);
// Negative scriptsizemultipliers are not parsed
if (NS_SUCCEEDED(errorCode) && floatValue >= 0.0f) {
aDecls.SetNumberValue(eCSSProperty__moz_script_size_multiplier,
floatValue);
} else {
ReportParseErrorNoTag(str, nsGkAtoms::scriptsizemultiplier_,
aDecls.Document());
if (!StaticPrefs::mathml_scriptsizemultiplier_attribute_disabled()) {
const nsAttrValue* value =
aBuilder.GetAttr(nsGkAtoms::scriptsizemultiplier_);
if (value && value->Type() == nsAttrValue::eString &&
!aBuilder.PropertyIsSet(eCSSProperty__moz_script_size_multiplier)) {
aBuilder.Document().WarnOnceAbout(
dom::DeprecatedOperations::
eMathML_DeprecatedScriptsizemultiplierAttribute);
auto str = value->GetStringValue();
str.CompressWhitespace();
// MathML numbers can't have leading '+'
if (str.Length() > 0 && str.CharAt(0) != '+') {
nsresult errorCode;
float floatValue = str.ToFloat(&errorCode);
// Negative scriptsizemultipliers are not parsed
if (NS_SUCCEEDED(errorCode) && floatValue >= 0.0f) {
aBuilder.SetNumberValue(eCSSProperty__moz_script_size_multiplier,
floatValue);
} else {
ReportParseErrorNoTag(str, nsGkAtoms::scriptsizemultiplier_,
aBuilder.Document());
}
}
}
}
@ -401,21 +433,24 @@ void MathMLElement::MapMathMLAttributesInto(
// We don't allow negative values.
// Unitless and percent values give a multiple of the default value.
//
value = aAttributes->GetAttr(nsGkAtoms::scriptminsize_);
if (value && value->Type() == nsAttrValue::eString &&
!aDecls.PropertyIsSet(eCSSProperty__moz_script_min_size)) {
aDecls.Document()->WarnOnceAbout(
dom::DeprecatedOperations::eMathML_DeprecatedScriptminsizeAttribute);
nsCSSValue scriptMinSize;
ParseNumericValue(value->GetStringValue(), scriptMinSize, 0,
aDecls.Document());
if (!StaticPrefs::mathml_scriptminsize_attribute_disabled()) {
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::scriptminsize_);
if (value && value->Type() == nsAttrValue::eString &&
!aBuilder.PropertyIsSet(eCSSProperty__moz_script_min_size)) {
aBuilder.Document().WarnOnceAbout(
dom::DeprecatedOperations::eMathML_DeprecatedScriptminsizeAttribute);
nsCSSValue scriptMinSize;
ParseNumericValue(value->GetStringValue(), scriptMinSize, 0,
&aBuilder.Document());
if (scriptMinSize.GetUnit() == eCSSUnit_Percent) {
scriptMinSize.SetFloatValue(8.0 * scriptMinSize.GetPercentValue(),
eCSSUnit_Point);
}
if (scriptMinSize.GetUnit() != eCSSUnit_Null) {
aDecls.SetLengthValue(eCSSProperty__moz_script_min_size, scriptMinSize);
if (scriptMinSize.GetUnit() == eCSSUnit_Percent) {
scriptMinSize.SetFloatValue(8.0f * scriptMinSize.GetPercentValue(),
eCSSUnit_Point);
}
if (scriptMinSize.GetUnit() != eCSSUnit_Null) {
aBuilder.SetLengthValue(eCSSProperty__moz_script_min_size,
scriptMinSize);
}
}
}
@ -430,9 +465,9 @@ void MathMLElement::MapMathMLAttributesInto(
// values: ( "+" | "-" )? unsigned-integer
// default: inherited
//
value = aAttributes->GetAttr(nsGkAtoms::scriptlevel_);
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::scriptlevel_);
if (value && value->Type() == nsAttrValue::eString &&
!aDecls.PropertyIsSet(eCSSProperty_math_depth)) {
!aBuilder.PropertyIsSet(eCSSProperty_math_depth)) {
auto str = value->GetStringValue();
str.CompressWhitespace();
if (str.Length() > 0) {
@ -441,26 +476,27 @@ void MathMLElement::MapMathMLAttributesInto(
if (NS_SUCCEEDED(errorCode)) {
char16_t ch = str.CharAt(0);
bool isRelativeScriptLevel = (ch == '+' || ch == '-');
aDecls.SetMathDepthValue(intValue, isRelativeScriptLevel);
aBuilder.SetMathDepthValue(intValue, isRelativeScriptLevel);
} else {
ReportParseErrorNoTag(str, nsGkAtoms::scriptlevel_, aDecls.Document());
ReportParseErrorNoTag(str, nsGkAtoms::scriptlevel_,
aBuilder.Document());
}
}
}
// mathsize
// https://w3c.github.io/mathml-core/#dfn-mathsize
value = aAttributes->GetAttr(nsGkAtoms::mathsize_);
value = aBuilder.GetAttr(nsGkAtoms::mathsize_);
if (value && value->Type() == nsAttrValue::eString &&
!aDecls.PropertyIsSet(eCSSProperty_font_size)) {
!aBuilder.PropertyIsSet(eCSSProperty_font_size)) {
auto str = value->GetStringValue();
nsCSSValue fontSize;
ParseNumericValue(str, fontSize, 0, nullptr);
if (fontSize.GetUnit() == eCSSUnit_Percent) {
aDecls.SetPercentValue(eCSSProperty_font_size,
fontSize.GetPercentValue());
aBuilder.SetPercentValue(eCSSProperty_font_size,
fontSize.GetPercentValue());
} else if (fontSize.GetUnit() != eCSSUnit_Null) {
aDecls.SetLengthValue(eCSSProperty_font_size, fontSize);
aBuilder.SetLengthValue(eCSSProperty_font_size, fontSize);
}
}
@ -475,9 +511,9 @@ void MathMLElement::MapMathMLAttributesInto(
// "monospace" | "initial" | "tailed" | "looped" | "stretched"
// default: normal (except on <mi>)
//
value = aAttributes->GetAttr(nsGkAtoms::mathvariant_);
value = aBuilder.GetAttr(nsGkAtoms::mathvariant_);
if (value && value->Type() == nsAttrValue::eString &&
!aDecls.PropertyIsSet(eCSSProperty__moz_math_variant)) {
!aBuilder.PropertyIsSet(eCSSProperty__moz_math_variant)) {
auto str = value->GetStringValue();
str.CompressWhitespace();
static const char sizes[19][23] = {"normal",
@ -519,7 +555,7 @@ void MathMLElement::MapMathMLAttributesInto(
StyleMathVariant::Stretched};
for (uint32_t i = 0; i < ArrayLength(sizes); ++i) {
if (str.LowerCaseEqualsASCII(sizes[i])) {
aDecls.SetKeywordValue(eCSSProperty__moz_math_variant, values[i]);
aBuilder.SetKeywordValue(eCSSProperty__moz_math_variant, values[i]);
break;
}
}
@ -527,60 +563,34 @@ void MathMLElement::MapMathMLAttributesInto(
// mathbackground
// https://w3c.github.io/mathml-core/#dfn-mathbackground
value = aAttributes->GetAttr(nsGkAtoms::mathbackground_);
value = aBuilder.GetAttr(nsGkAtoms::mathbackground_);
if (value) {
nscolor color;
if (value->GetColorValue(color)) {
aDecls.SetColorValueIfUnset(eCSSProperty_background_color, color);
aBuilder.SetColorValueIfUnset(eCSSProperty_background_color, color);
}
}
// mathcolor
// https://w3c.github.io/mathml-core/#dfn-mathcolor
value = aAttributes->GetAttr(nsGkAtoms::mathcolor_);
value = aBuilder.GetAttr(nsGkAtoms::mathcolor_);
nscolor color;
if (value && value->GetColorValue(color)) {
aDecls.SetColorValueIfUnset(eCSSProperty_color, color);
}
// width
//
// "Specifies the desired width of the entire table and is intended for
// visual user agents. When the value is a percentage value, the value is
// relative to the horizontal space a MathML renderer has available for the
// math element. When the value is "auto", the MathML renderer should
// calculate the table width from its contents using whatever layout
// algorithm it chooses. "
//
// values: "auto" | length
// default: auto
//
if (!aDecls.PropertyIsSet(eCSSProperty_width)) {
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
nsCSSValue width;
// This does not handle auto and unitless values
if (value && value->Type() == nsAttrValue::eString) {
ParseNumericValue(value->GetStringValue(), width, 0, aDecls.Document());
if (width.GetUnit() == eCSSUnit_Percent) {
aDecls.SetPercentValue(eCSSProperty_width, width.GetPercentValue());
} else if (width.GetUnit() != eCSSUnit_Null) {
aDecls.SetLengthValue(eCSSProperty_width, width);
}
}
aBuilder.SetColorValueIfUnset(eCSSProperty_color, color);
}
// dir
// https://w3c.github.io/mathml-core/#dfn-dir
value = aAttributes->GetAttr(nsGkAtoms::dir);
value = aBuilder.GetAttr(nsGkAtoms::dir);
if (value && value->Type() == nsAttrValue::eString &&
!aDecls.PropertyIsSet(eCSSProperty_direction)) {
!aBuilder.PropertyIsSet(eCSSProperty_direction)) {
auto str = value->GetStringValue();
static const char dirs[][4] = {"ltr", "rtl"};
static const StyleDirection dirValues[MOZ_ARRAY_LENGTH(dirs)] = {
StyleDirection::Ltr, StyleDirection::Rtl};
for (uint32_t i = 0; i < ArrayLength(dirs); ++i) {
if (str.LowerCaseEqualsASCII(dirs[i])) {
aDecls.SetKeywordValue(eCSSProperty_direction, dirValues[i]);
aBuilder.SetKeywordValue(eCSSProperty_direction, dirValues[i]);
break;
}
}
@ -588,16 +598,16 @@ void MathMLElement::MapMathMLAttributesInto(
// displaystyle
// https://mathml-refresh.github.io/mathml-core/#dfn-displaystyle
value = aAttributes->GetAttr(nsGkAtoms::displaystyle_);
value = aBuilder.GetAttr(nsGkAtoms::displaystyle_);
if (value && value->Type() == nsAttrValue::eString &&
!aDecls.PropertyIsSet(eCSSProperty_math_style)) {
!aBuilder.PropertyIsSet(eCSSProperty_math_style)) {
auto str = value->GetStringValue();
static const char displaystyles[][6] = {"false", "true"};
static const StyleMathStyle mathStyle[MOZ_ARRAY_LENGTH(displaystyles)] = {
StyleMathStyle::Compact, StyleMathStyle::Normal};
for (uint32_t i = 0; i < ArrayLength(displaystyles); ++i) {
if (str.LowerCaseEqualsASCII(displaystyles[i])) {
aDecls.SetKeywordValue(eCSSProperty_math_style, mathStyle[i]);
aBuilder.SetKeywordValue(eCSSProperty_math_style, mathStyle[i]);
break;
}
}

View File

@ -8,7 +8,7 @@
#define mozilla_dom_MathMLElement_h_
#include "mozilla/Attributes.h"
#include "nsMappedAttributeElement.h"
#include "nsStyledElement.h"
#include "Link.h"
class nsCSSValue;
@ -18,13 +18,12 @@ class EventChainPostVisitor;
class EventChainPreVisitor;
namespace dom {
typedef nsMappedAttributeElement MathMLElementBase;
using MathMLElementBase = nsStyledElement;
/*
* The base class for MathML elements.
*/
class MathMLElement final : public MathMLElementBase,
public mozilla::dom::Link {
class MathMLElement final : public MathMLElementBase, public Link {
public:
explicit MathMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
explicit MathMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
@ -56,8 +55,9 @@ class MathMLElement final : public MathMLElementBase,
static bool ParseNumericValue(const nsString& aString, nsCSSValue& aCSSValue,
uint32_t aFlags, Document* aDocument);
static void MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
mozilla::MappedDeclarations&);
static void MapGlobalMathMLAttributesInto(
mozilla::MappedDeclarationsBuilder&);
static void MapMTableAttributesInto(mozilla::MappedDeclarationsBuilder&);
void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override;
MOZ_CAN_RUN_SCRIPT

View File

@ -20,7 +20,6 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/DeclarationBlock.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/PresShell.h"
@ -105,9 +104,7 @@ SVGEnumMapping SVGElement::sSVGUnitTypesMap[] = {
SVGElement::SVGElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: SVGElementBase(std::move(aNodeInfo)) {}
SVGElement::~SVGElement() {
OwnerDoc()->UnscheduleSVGForPresAttrEvaluation(this);
}
SVGElement::~SVGElement() = default;
JSObject* SVGElement::WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
@ -317,23 +314,6 @@ void SVGElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
nsIPrincipal* aSubjectPrincipal, bool aNotify) {
// We don't currently use nsMappedAttributes within SVG. If this changes, we
// need to be very careful because some nsAttrValues used by SVG point to
// member data of SVG elements and if an nsAttrValue outlives the SVG element
// whose data it points to (by virtue of being stored in
// mAttrs->mMappedAttributes, meaning it's shared between
// elements), the pointer will dangle. See bug 724680.
MOZ_ASSERT(!mAttrs.HasMappedAttrs(),
"Unexpected use of nsMappedAttributes within SVG");
// If this is an svg presentation attribute we need to map it into
// the content declaration block.
// XXX For some reason incremental mapping doesn't work, so for now
// just delete the style rule and lazily reconstruct it as needed).
if (aNamespaceID == kNameSpaceID_None && IsAttributeMapped(aName)) {
OwnerDoc()->ScheduleSVGForPresAttrEvaluation(this);
}
if (IsEventAttributeName(aName) && aValue) {
MOZ_ASSERT(aValue->Type() == nsAttrValue::eString,
"Expected string value for script body");
@ -925,9 +905,6 @@ nsChangeHint SVGElement::GetAttributeChangeHint(const nsAtom* aAttribute,
void SVGElement::NodeInfoChanged(Document* aOldDoc) {
SVGElementBase::NodeInfoChanged(aOldDoc);
aOldDoc->UnscheduleSVGForPresAttrEvaluation(this);
mContentDeclarationBlock = nullptr;
OwnerDoc()->ScheduleSVGForPresAttrEvaluation(this);
}
NS_IMETHODIMP_(bool)
@ -1042,10 +1019,8 @@ already_AddRefed<DOMSVGAnimatedString> SVGElement::ClassName() {
/* static */
bool SVGElement::UpdateDeclarationBlockFromLength(
DeclarationBlock& aBlock, nsCSSPropertyID aPropId,
StyleLockedDeclarationBlock& aBlock, nsCSSPropertyID aPropId,
const SVGAnimatedLength& aLength, ValToUse aValToUse) {
aBlock.AssertMutable();
float value;
if (aValToUse == ValToUse::Anim) {
value = aLength.GetAnimValInSpecifiedUnits();
@ -1054,8 +1029,8 @@ bool SVGElement::UpdateDeclarationBlockFromLength(
value = aLength.GetBaseValInSpecifiedUnits();
}
// SVG parser doesn't check non-negativity of some parsed value,
// we should not pass those to CSS side.
// SVG parser doesn't check non-negativity of some parsed value, we should not
// pass those to CSS side.
if (value < 0 &&
SVGGeometryProperty::IsNonNegativeGeometryProperty(aPropId)) {
return false;
@ -1065,11 +1040,9 @@ bool SVGElement::UpdateDeclarationBlockFromLength(
SVGLength::SpecifiedUnitTypeToCSSUnit(aLength.GetSpecifiedUnitType());
if (cssUnit == eCSSUnit_Percent) {
Servo_DeclarationBlock_SetPercentValue(aBlock.Raw(), aPropId,
value / 100.f);
Servo_DeclarationBlock_SetPercentValue(&aBlock, aPropId, value / 100.f);
} else {
Servo_DeclarationBlock_SetLengthValue(aBlock.Raw(), aPropId, value,
cssUnit);
Servo_DeclarationBlock_SetLengthValue(&aBlock, aPropId, value, cssUnit);
}
return true;
@ -1077,10 +1050,8 @@ bool SVGElement::UpdateDeclarationBlockFromLength(
/* static */
bool SVGElement::UpdateDeclarationBlockFromPath(
DeclarationBlock& aBlock, const SVGAnimatedPathSegList& aPath,
StyleLockedDeclarationBlock& aBlock, const SVGAnimatedPathSegList& aPath,
ValToUse aValToUse) {
aBlock.AssertMutable();
const SVGPathData& pathData =
aValToUse == ValToUse::Anim ? aPath.GetAnimValue() : aPath.GetBaseValue();
@ -1095,7 +1066,7 @@ bool SVGElement::UpdateDeclarationBlockFromPath(
// The normalization should be fixed in Bug 1489392. Besides, Bug 1714238
// will use the same data structure, so we may simplify this more.
const nsTArray<float>& asInFallibleArray = pathData.RawData();
Servo_DeclarationBlock_SetPathValue(aBlock.Raw(), eCSSProperty_d,
Servo_DeclarationBlock_SetPathValue(&aBlock, eCSSProperty_d,
&asInFallibleArray);
return true;
}
@ -1108,11 +1079,10 @@ namespace {
class MOZ_STACK_CLASS MappedAttrParser {
public:
explicit MappedAttrParser(SVGElement& aElement,
already_AddRefed<DeclarationBlock> aDecl)
StyleLockedDeclarationBlock* aDecl)
: mElement(aElement), mDecl(aDecl) {
if (mDecl) {
mDecl->AssertMutable();
Servo_DeclarationBlock_Clear(mDecl->Raw());
Servo_DeclarationBlock_Clear(mDecl);
}
}
~MappedAttrParser() {
@ -1130,15 +1100,15 @@ class MOZ_STACK_CLASS MappedAttrParser {
void TellStyleAlreadyParsedResult(const SVGAnimatedPathSegList& aPath);
// If we've parsed any values for mapped attributes, this method returns the
// already_AddRefed css::Declaration that incorporates the parsed
// values. Otherwise, this method returns null.
already_AddRefed<DeclarationBlock> TakeDeclarationBlock() {
// already_AddRefed declaration block that incorporates the parsed values.
// Otherwise, this method returns null.
already_AddRefed<StyleLockedDeclarationBlock> TakeDeclarationBlock() {
return mDecl.forget();
}
DeclarationBlock& EnsureDeclarationBlock() {
StyleLockedDeclarationBlock& EnsureDeclarationBlock() {
if (!mDecl) {
mDecl = new DeclarationBlock();
mDecl = Servo_DeclarationBlock_CreateEmpty().Consume();
}
return *mDecl;
}
@ -1155,7 +1125,7 @@ class MOZ_STACK_CLASS MappedAttrParser {
SVGElement& mElement;
// Declaration for storing parsed values (lazily initialized).
RefPtr<DeclarationBlock> mDecl;
RefPtr<StyleLockedDeclarationBlock> mDecl;
// URL data for parsing stuff. Also lazy.
RefPtr<URLExtraData> mExtraData;
@ -1172,7 +1142,7 @@ void MappedAttrParser::ParseMappedAttrValue(nsAtom* aMappedAttrName,
auto* doc = mElement.OwnerDoc();
changed = Servo_DeclarationBlock_SetPropertyById(
EnsureDeclarationBlock().Raw(), propertyID, &value, false,
&EnsureDeclarationBlock(), propertyID, &value, false,
&EnsureExtraData(), ParsingMode::AllowUnitlessLength,
doc->GetCompatibilityMode(), doc->CSSLoader(), StyleCssRuleType::Style,
{});
@ -1193,7 +1163,7 @@ void MappedAttrParser::ParseMappedAttrValue(nsAtom* aMappedAttrName,
if (aMappedAttrName == nsGkAtoms::lang) {
propertyID = eCSSProperty__x_lang;
RefPtr<nsAtom> atom = NS_Atomize(aMappedAttrValue);
Servo_DeclarationBlock_SetIdentStringValue(EnsureDeclarationBlock().Raw(),
Servo_DeclarationBlock_SetIdentStringValue(&EnsureDeclarationBlock(),
propertyID, atom);
}
}
@ -1218,10 +1188,11 @@ void MappedAttrParser::TellStyleAlreadyParsedResult(
//----------------------------------------------------------------------
// Implementation Helpers:
void SVGElement::UpdateContentDeclarationBlock() {
MappedAttrParser mappedAttrParser(*this, mContentDeclarationBlock.forget());
void SVGElement::UpdateMappedDeclarationBlock() {
MOZ_ASSERT(IsPendingMappedAttributeEvaluation());
MappedAttrParser mappedAttrParser(*this, mAttrs.GetMappedDeclarationBlock());
bool lengthAffectsStyle =
const bool lengthAffectsStyle =
SVGGeometryProperty::ElementMapsLengthsToStyle(this);
uint32_t i = 0;
@ -1279,7 +1250,7 @@ void SVGElement::UpdateContentDeclarationBlock() {
info.mValue->ToString(value);
mappedAttrParser.ParseMappedAttrValue(attrName->Atom(), value);
}
mContentDeclarationBlock = mappedAttrParser.TakeDeclarationBlock();
mAttrs.SetMappedDeclarationBlock(mappedAttrParser.TakeDeclarationBlock());
}
/**
@ -2371,16 +2342,6 @@ void SVGElement::FlushAnimations() {
void SVGElement::AddSizeOfExcludingThis(nsWindowSizes& aSizes,
size_t* aNodeSize) const {
Element::AddSizeOfExcludingThis(aSizes, aNodeSize);
// These are owned by the element and not referenced from the stylesheets.
// They're referenced from the rule tree, but the rule nodes don't measure
// their style source (since they're non-owning), so unconditionally reporting
// them even though it's a refcounted object is ok.
if (mContentDeclarationBlock) {
aSizes.mLayoutSvgMappedDeclarations +=
mContentDeclarationBlock->SizeofIncludingThis(
aSizes.mState.mMallocSizeOf);
}
}
} // namespace mozilla::dom

View File

@ -42,7 +42,6 @@ nsresult NS_NewSVGElement(mozilla::dom::Element** aResult,
class mozAutoDocUpdate;
namespace mozilla {
class DeclarationBlock;
class SVGAnimatedBoolean;
class SVGAnimatedEnumeration;
@ -126,6 +125,7 @@ class SVGElement : public SVGElementBase // nsIContent
void NodeInfoChanged(Document* aOldDoc) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
void UpdateMappedDeclarationBlock();
NS_IMPL_FROMNODE(SVGElement, kNameSpaceID_SVG)
@ -181,12 +181,11 @@ class SVGElement : public SVGElementBase // nsIContent
void SetLength(nsAtom* aName, const SVGAnimatedLength& aLength);
enum class ValToUse { Base, Anim };
static bool UpdateDeclarationBlockFromLength(DeclarationBlock& aBlock,
nsCSSPropertyID aPropId,
const SVGAnimatedLength& aLength,
ValToUse aValToUse);
static bool UpdateDeclarationBlockFromLength(
StyleLockedDeclarationBlock& aBlock, nsCSSPropertyID aPropId,
const SVGAnimatedLength& aLength, ValToUse aValToUse);
static bool UpdateDeclarationBlockFromPath(
DeclarationBlock& aBlock, const SVGAnimatedPathSegList& aPath,
StyleLockedDeclarationBlock& aBlock, const SVGAnimatedPathSegList& aPath,
ValToUse aValToUse);
nsAttrValue WillChangeLength(uint8_t aAttrEnum,
@ -331,11 +330,6 @@ class SVGElement : public SVGElementBase // nsIContent
SVGElement* GetViewportElement();
already_AddRefed<mozilla::dom::DOMSVGAnimatedString> ClassName();
void UpdateContentDeclarationBlock();
const mozilla::DeclarationBlock* GetContentDeclarationBlock() const {
return mContentDeclarationBlock.get();
}
bool Autofocus() const { return GetBoolAttr(nsGkAtoms::autofocus); }
void SetAutofocus(bool aAutofocus, ErrorResult& aRv) {
if (aAutofocus) {
@ -515,7 +509,6 @@ class SVGElement : public SVGElementBase // nsIContent
SVGAnimatedClass mClassAttribute;
UniquePtr<nsAttrValue> mClassAnimAttr;
RefPtr<mozilla::DeclarationBlock> mContentDeclarationBlock;
};
NS_DEFINE_STATIC_IID_ACCESSOR(SVGElement, MOZILLA_SVGELEMENT_IID)

View File

@ -90,7 +90,7 @@ SimpleTest.waitForFocus(() => {
SpecialPowers.doCommand(window, "cmd_backgroundColor", "#00ff00");
is(
editor.outerHTML,
"<div style=\"background-color: rgb(255, 0, 0);\" contenteditable=\"\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p></div></div>",
"<div contenteditable=\"\" style=\"background-color: rgb(255, 0, 0);\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p></div></div>",
"cmd_backgroundColor should set background of the closest block element from the caret in a text node"
);
@ -102,7 +102,7 @@ SimpleTest.waitForFocus(() => {
SpecialPowers.doCommand(window, "cmd_backgroundColor", "#00ff00");
is(
editor.outerHTML,
"<div style=\"background-color: rgb(0, 255, 0);\" contenteditable=\"\">abc</div>",
"<div contenteditable=\"\" style=\"background-color: rgb(0, 255, 0);\">abc</div>",
"cmd_backgroundColor should set background of the editing host which is direct block parent from the caret in a text node"
);
@ -114,7 +114,7 @@ SimpleTest.waitForFocus(() => {
SpecialPowers.doCommand(window, "cmd_backgroundColor", "#00ff00");
is(
editor.outerHTML,
"<div style=\"background-color: rgb(255, 0, 0);\" contenteditable=\"\"><div contenteditable=\"false\"><span contenteditable=\"true\">abc</span></div></div>",
"<div contenteditable=\"\" style=\"background-color: rgb(255, 0, 0);\"><div contenteditable=\"false\"><span contenteditable=\"true\">abc</span></div></div>",
"cmd_backgroundColor should not set background color of inline editing host nor its non-editable parent block"
);
@ -126,7 +126,7 @@ SimpleTest.waitForFocus(() => {
SpecialPowers.doCommand(window, "cmd_backgroundColor", "#00ff00");
is(
editor.outerHTML,
"<div style=\"background-color: rgb(255, 0, 0);\" contenteditable=\"\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>ab<br>c</span></p></div></div>",
"<div contenteditable=\"\" style=\"background-color: rgb(255, 0, 0);\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>ab<br>c</span></p></div></div>",
"cmd_backgroundColor should set background of the closest block element when selection a leaf element"
);
@ -138,7 +138,7 @@ SimpleTest.waitForFocus(() => {
SpecialPowers.doCommand(window, "cmd_backgroundColor", "#00ff00");
is(
editor.outerHTML,
"<div style=\"background-color: rgb(255, 0, 0);\" contenteditable=\"\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p></div></div>",
"<div contenteditable=\"\" style=\"background-color: rgb(255, 0, 0);\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p></div></div>",
"cmd_backgroundColor should set background of the selected block element"
);
@ -150,7 +150,7 @@ SimpleTest.waitForFocus(() => {
SpecialPowers.doCommand(window, "cmd_backgroundColor", "#00ff00");
is(
editor.outerHTML,
"<div style=\"background-color: rgb(255, 0, 0);\" contenteditable=\"\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p>" +
"<div contenteditable=\"\" style=\"background-color: rgb(255, 0, 0);\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p>" +
"<p style=\"background-color: rgb(0, 255, 0);\"><span>def</span></p>" +
"<p style=\"background-color: rgb(0, 255, 0);\"><span>ghi</span></p></div></div>",
"cmd_backgroundColor should set background of the paragraph elements in the selection range"
@ -164,7 +164,7 @@ SimpleTest.waitForFocus(() => {
SpecialPowers.doCommand(window, "cmd_backgroundColor", "#00ff00");
is(
editor.outerHTML,
"<div style=\"background-color: rgb(255, 0, 0);\" contenteditable=\"\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p>" +
"<div contenteditable=\"\" style=\"background-color: rgb(255, 0, 0);\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p>" +
"<p style=\"background-color: rgb(0, 255, 0);\"><span contenteditable=\"false\">def</span></p>" +
"<p style=\"background-color: rgb(0, 255, 0);\"><span>ghi</span></p></div></div>",
"cmd_backgroundColor should set background of the paragraph elements in the selection range even if a paragraph has only non-editable content"
@ -178,7 +178,7 @@ SimpleTest.waitForFocus(() => {
SpecialPowers.doCommand(window, "cmd_backgroundColor", "#00ff00");
is(
editor.outerHTML,
"<div style=\"background-color: rgb(255, 0, 0);\" contenteditable=\"\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p>" +
"<div contenteditable=\"\" style=\"background-color: rgb(255, 0, 0);\"><div><p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p>" +
"<p contenteditable=\"false\"><span>def</span></p>" +
"<p style=\"background-color: rgb(0, 255, 0);\"><span>ghi</span></p></div></div>",
"cmd_backgroundColor should set background of the paragraph elements in the selection range except the non-editable paragraph"
@ -192,7 +192,7 @@ SimpleTest.waitForFocus(() => {
SpecialPowers.doCommand(window, "cmd_backgroundColor", "#00ff00");
is(
editor.outerHTML,
"<div style=\"background-color: rgb(255, 0, 0);\" contenteditable=\"\"><div style=\"background-color: rgb(0, 255, 0);\">" +
"<div contenteditable=\"\" style=\"background-color: rgb(255, 0, 0);\"><div style=\"background-color: rgb(0, 255, 0);\">" +
"<p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p>" +
"<span>def</span>" +
"<p style=\"background-color: rgb(0, 255, 0);\"><span>ghi</span></p></div></div>",
@ -207,7 +207,7 @@ SimpleTest.waitForFocus(() => {
SpecialPowers.doCommand(window, "cmd_backgroundColor", "#00ff00");
is(
editor.outerHTML,
"<div style=\"background-color: rgb(0, 255, 0);\" contenteditable=\"\">" +
"<div contenteditable=\"\" style=\"background-color: rgb(0, 255, 0);\">" +
"<p style=\"background-color: rgb(0, 255, 0);\"><span>abc</span></p>" +
"<span>def</span>" +
"<p style=\"background-color: rgb(0, 255, 0);\"><span>ghi</span></p></div>",

View File

@ -458,7 +458,7 @@ SimpleTest.waitForFocus(() => {
range.selectNode(document.getElementById("select"));
selection.addRange(range);
getTableEditor().deleteTableRow(1);
is(editor.innerHTML, '<table><tbody><tr><td rowspan="2" valign="top"><br></td><td>cell2-2</td></tr><tr><td>cell3-2</td></tr></tbody></table>',
is(editor.innerHTML, '<table><tbody><tr><td valign="top" rowspan="2"><br></td><td>cell2-2</td></tr><tr><td>cell3-2</td></tr></tbody></table>',
"nsITableEditor.deleteTableRow(1) with a selected cell is rowspan=\"3\" should delete the first row and add empty cell whose rowspan is 2 to the second row");
is(beforeInputEvents.length, 1,
'Only one "beforeinput" event should be fired when a cell is selected and its rowspan is 3');

View File

@ -3488,9 +3488,6 @@ void RestyleManager::AttributeChanged(Element* aElement, int32_t aNameSpaceID,
restyleHint |= RestyleHint::RESTYLE_STYLE_ATTRIBUTE;
} else if (AttributeChangeRequiresSubtreeRestyle(*aElement, aAttribute)) {
restyleHint |= RestyleHint::RestyleSubtree();
} else if (aElement->IsAttributeMapped(aAttribute)) {
// FIXME(emilio): Does this really need to re-selector-match?
restyleHint |= RestyleHint::RESTYLE_SELF;
} else if (aElement->IsInShadowTree() && aAttribute == nsGkAtoms::part) {
// TODO(emilio, bug 1598094): Maybe finer-grained invalidation for part
// attribute changes?

View File

@ -8,7 +8,6 @@
#include "mozilla/AttributeStyles.h"
#include "nsMappedAttributes.h"
#include "nsGkAtoms.h"
#include "nsPresContext.h"
#include "mozilla/dom/Document.h"
@ -31,45 +30,7 @@ namespace mozilla {
// -----------------------------------------------------------
struct MappedAttrTableEntry : public PLDHashEntryHdr {
nsMappedAttributes* mAttributes;
};
static PLDHashNumber MappedAttrTable_HashKey(const void* key) {
nsMappedAttributes* attributes =
static_cast<nsMappedAttributes*>(const_cast<void*>(key));
return attributes->HashValue();
}
static void MappedAttrTable_ClearEntry(PLDHashTable* table,
PLDHashEntryHdr* hdr) {
MappedAttrTableEntry* entry = static_cast<MappedAttrTableEntry*>(hdr);
entry->mAttributes->DropAttributeStylesReference();
memset(entry, 0, sizeof(MappedAttrTableEntry));
}
static bool MappedAttrTable_MatchEntry(const PLDHashEntryHdr* hdr,
const void* key) {
nsMappedAttributes* attributes =
static_cast<nsMappedAttributes*>(const_cast<void*>(key));
const MappedAttrTableEntry* entry =
static_cast<const MappedAttrTableEntry*>(hdr);
return attributes->Equals(entry->mAttributes);
}
static const PLDHashTableOps MappedAttrTable_Ops = {
MappedAttrTable_HashKey, MappedAttrTable_MatchEntry,
PLDHashTable::MoveEntryStub, MappedAttrTable_ClearEntry, nullptr};
// -----------------------------------------------------------
// -----------------------------------------------------------
AttributeStyles::AttributeStyles(Document* aDocument)
: mDocument(aDocument),
mMappedAttrTable(&MappedAttrTable_Ops, sizeof(MappedAttrTableEntry)) {
AttributeStyles::AttributeStyles(Document* aDocument) : mDocument(aDocument) {
MOZ_ASSERT(aDocument);
}
@ -81,9 +42,6 @@ void AttributeStyles::Reset() {
mServoUnvisitedLinkDecl = nullptr;
mServoVisitedLinkDecl = nullptr;
mServoActiveLinkDecl = nullptr;
mMappedAttrTable.Clear();
mMappedAttrsDirty = false;
}
nsresult AttributeStyles::ImplLinkColorSetter(
@ -117,54 +75,9 @@ nsresult AttributeStyles::SetVisitedLinkColor(nscolor aColor) {
return ImplLinkColorSetter(mServoVisitedLinkDecl, aColor);
}
already_AddRefed<nsMappedAttributes> AttributeStyles::UniqueMappedAttributes(
nsMappedAttributes* aMapped) {
mMappedAttrsDirty = true;
auto entry = static_cast<MappedAttrTableEntry*>(
mMappedAttrTable.Add(aMapped, fallible));
if (!entry) {
return nullptr;
}
if (!entry->mAttributes) {
// We added a new entry to the hashtable, so we have a new unique set.
entry->mAttributes = aMapped;
}
RefPtr<nsMappedAttributes> ret = entry->mAttributes;
return ret.forget();
}
void AttributeStyles::DropMappedAttributes(nsMappedAttributes* aMapped) {
NS_ENSURE_TRUE_VOID(aMapped);
#ifdef DEBUG
uint32_t entryCount = mMappedAttrTable.EntryCount() - 1;
#endif
mMappedAttrTable.Remove(aMapped);
NS_ASSERTION(entryCount == mMappedAttrTable.EntryCount(), "not removed");
}
void AttributeStyles::CalculateMappedServoDeclarations() {
for (auto iter = mMappedAttrTable.ConstIter(); !iter.Done(); iter.Next()) {
MappedAttrTableEntry* attr = static_cast<MappedAttrTableEntry*>(iter.Get());
if (attr->mAttributes->GetServoStyle()) {
// Only handle cases which haven't been filled in already
continue;
}
attr->mAttributes->LazilyResolveServoDeclaration(mDocument);
}
}
size_t AttributeStyles::DOMSizeOfIncludingThis(
MallocSizeOf aMallocSizeOf) const {
size_t n = aMallocSizeOf(this);
n += mMappedAttrTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (auto iter = mMappedAttrTable.ConstIter(); !iter.Done(); iter.Next()) {
auto entry = static_cast<MappedAttrTableEntry*>(iter.Get());
n += entry->mAttributes->SizeOfIncludingThis(aMallocSizeOf);
}
// Measurement of the following members may be added later if DMD finds it is
// worthwhile:
// - mServoUnvisitedLinkDecl;
@ -173,7 +86,6 @@ size_t AttributeStyles::DOMSizeOfIncludingThis(
//
// The following members are not measured:
// - mDocument, because it's non-owning
return n;
}

View File

@ -22,7 +22,6 @@
#include "nsString.h"
struct MiscContainer;
class nsMappedAttributes;
namespace mozilla {
struct StyleLockedDeclarationBlock;
namespace dom {
@ -53,14 +52,6 @@ class AttributeStyles final {
return mServoActiveLinkDecl;
}
// Mapped Attribute management methods
already_AddRefed<nsMappedAttributes> UniqueMappedAttributes(
nsMappedAttributes* aMapped);
void DropMappedAttributes(nsMappedAttributes* aMapped);
// For each mapped presentation attribute in the cache, resolve the attached
// DeclarationBlock by running the mapping to Servo specified values.
void CalculateMappedServoDeclarations();
void CacheStyleAttr(const nsAString& aSerialized, MiscContainer* aValue) {
mCachedStyleAttrs.InsertOrUpdate(aSerialized, aValue);
}
@ -87,13 +78,7 @@ class AttributeStyles final {
RefPtr<StyleLockedDeclarationBlock> mServoUnvisitedLinkDecl;
RefPtr<StyleLockedDeclarationBlock> mServoVisitedLinkDecl;
RefPtr<StyleLockedDeclarationBlock> mServoActiveLinkDecl;
PLDHashTable mMappedAttrTable;
nsTHashMap<nsStringHashKey, MiscContainer*> mCachedStyleAttrs;
// Whether or not the mapped attributes table
// has been changed since the last call to
// CalculateMappedServoDeclarations()
bool mMappedAttrsDirty = false;
};
} // namespace mozilla

View File

@ -31,7 +31,6 @@
#include "nsINode.h"
#include "nsIURI.h"
#include "nsFontMetrics.h"
#include "nsMappedAttributes.h"
#include "nsNameSpaceManager.h"
#include "nsNetUtil.h"
#include "nsProxyRelease.h"
@ -391,29 +390,16 @@ void Gecko_UnsetDirtyStyleAttr(const Element* aElement) {
const StyleLockedDeclarationBlock*
Gecko_GetHTMLPresentationAttrDeclarationBlock(const Element* aElement) {
if (const nsMappedAttributes* attrs = aElement->GetMappedAttributes()) {
MOZ_ASSERT(!aElement->IsSVGElement(), "SVG doesn't use nsMappedAttributes");
return attrs->GetServoStyle();
}
if (const auto* svg = SVGElement::FromNode(aElement)) {
if (const auto* decl = svg->GetContentDeclarationBlock()) {
return decl->Raw();
}
}
return nullptr;
return aElement->GetMappedAttributeStyle();
}
const StyleLockedDeclarationBlock* Gecko_GetExtraContentStyleDeclarations(
const Element* aElement) {
if (const auto* cell = HTMLTableCellElement::FromNode(aElement)) {
if (nsMappedAttributes* attrs =
cell->GetMappedAttributesInheritedFromTable()) {
return attrs->GetServoStyle();
}
} else if (const auto* img = HTMLImageElement::FromNode(aElement)) {
if (const auto* attrs = img->GetMappedAttributesFromSource()) {
return attrs->GetServoStyle();
}
return cell->GetMappedAttributesInheritedFromTable();
}
if (const auto* img = HTMLImageElement::FromNode(aElement)) {
return img->GetMappedAttributesFromSource();
}
return nullptr;
}

View File

@ -4,7 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MappedDeclarations.h"
#include "MappedDeclarationsBuilder.h"
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
@ -13,9 +13,9 @@
namespace mozilla {
void MappedDeclarations::SetIdentAtomValue(nsCSSPropertyID aId,
nsAtom* aValue) {
Servo_DeclarationBlock_SetIdentStringValue(mDecl, aId, aValue);
void MappedDeclarationsBuilder::SetIdentAtomValue(nsCSSPropertyID aId,
nsAtom* aValue) {
Servo_DeclarationBlock_SetIdentStringValue(&EnsureDecls(), aId, aValue);
if (aId == eCSSProperty__x_lang) {
// This forces the lang prefs result to be cached so that we can access them
// off main thread during traversal.
@ -23,11 +23,11 @@ void MappedDeclarations::SetIdentAtomValue(nsCSSPropertyID aId,
// FIXME(emilio): Can we move mapped attribute declarations across
// documents? Isn't this wrong in that case? This is pretty out of place
// anyway.
mDocument->ForceCacheLang(aValue);
mDocument.ForceCacheLang(aValue);
}
}
void MappedDeclarations::SetBackgroundImage(const nsAttrValue& aValue) {
void MappedDeclarationsBuilder::SetBackgroundImage(const nsAttrValue& aValue) {
if (aValue.Type() != nsAttrValue::eURL) {
return;
}
@ -36,7 +36,7 @@ void MappedDeclarations::SetBackgroundImage(const nsAttrValue& aValue) {
nsAutoCString utf8;
CopyUTF16toUTF8(str, utf8);
Servo_DeclarationBlock_SetBackgroundImage(
mDecl, &utf8, mDocument->DefaultStyleAttrURLData());
&EnsureDecls(), &utf8, mDocument.DefaultStyleAttrURLData());
}
} // namespace mozilla

View File

@ -6,11 +6,12 @@
/* Representation of a declaration block used for attribute mapping */
#ifndef mozilla_MappedDeclarations_h
#define mozilla_MappedDeclarations_h
#ifndef mozilla_MappedDeclarationsBuilder_h
#define mozilla_MappedDeclarationsBuilder_h
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/ServoBindingTypes.h"
#include "mozilla/dom/Element.h"
#include "mozilla/ServoBindings.h"
#include "nsCSSPropertyID.h"
#include "nsCSSValue.h"
@ -23,26 +24,30 @@ namespace mozilla {
// This provides a convenient interface for attribute mappers
// (MapAttributesIntoRule) to modify the presentation attribute declaration
// block for a given element.
class MappedDeclarations final {
class MOZ_STACK_CLASS MappedDeclarationsBuilder final {
public:
explicit MappedDeclarations(
dom::Document* aDoc, already_AddRefed<StyleLockedDeclarationBlock> aDecls)
: mDocument(aDoc), mDecl(aDecls) {
MOZ_ASSERT(mDecl);
explicit MappedDeclarationsBuilder(
dom::Element& aElement, dom::Document& aDoc,
StyleLockedDeclarationBlock* aDecls = nullptr)
: mDocument(aDoc), mElement(aElement), mDecls(aDecls) {
if (mDecls) {
Servo_DeclarationBlock_Clear(mDecls);
}
}
~MappedDeclarations() { MOZ_ASSERT(!mDecl, "Forgot to take the block?"); }
~MappedDeclarationsBuilder() {
MOZ_ASSERT(!mDecls, "Forgot to take the block?");
}
dom::Document* Document() { return mDocument; }
dom::Document& Document() { return mDocument; }
already_AddRefed<StyleLockedDeclarationBlock> TakeDeclarationBlock() {
MOZ_ASSERT(mDecl);
return mDecl.forget();
return mDecls.forget();
}
// Check if we already contain a certain longhand
bool PropertyIsSet(nsCSSPropertyID aId) const {
return Servo_DeclarationBlock_PropertyIsSet(mDecl, aId);
return mDecls && Servo_DeclarationBlock_PropertyIsSet(mDecls, aId);
}
// Set a property to an identifier (string)
@ -67,7 +72,7 @@ class MappedDeclarations final {
// Set a property to a keyword (usually NS_STYLE_* or StyleFoo::*)
void SetKeywordValue(nsCSSPropertyID aId, int32_t aValue) {
Servo_DeclarationBlock_SetKeywordValue(mDecl, aId, aValue);
Servo_DeclarationBlock_SetKeywordValue(&EnsureDecls(), aId, aValue);
}
void SetKeywordValueIfUnset(nsCSSPropertyID aId, int32_t aValue) {
@ -93,28 +98,30 @@ class MappedDeclarations final {
// Set a property to an integer value
void SetIntValue(nsCSSPropertyID aId, int32_t aValue) {
Servo_DeclarationBlock_SetIntValue(mDecl, aId, aValue);
Servo_DeclarationBlock_SetIntValue(&EnsureDecls(), aId, aValue);
}
// Set "math-depth: <integer>" or "math-depth: add(<integer>)"
void SetMathDepthValue(int32_t aValue, bool aIsRelative) {
Servo_DeclarationBlock_SetMathDepthValue(mDecl, aValue, aIsRelative);
Servo_DeclarationBlock_SetMathDepthValue(&EnsureDecls(), aValue,
aIsRelative);
}
// Set "counter-reset: list-item <integer>". If aIsReversed is true then
// "list-item" instead becomes "reversed(list-item)".
void SetCounterResetListItem(int32_t aValue, bool aIsReversed) {
Servo_DeclarationBlock_SetCounterResetListItem(mDecl, aValue, aIsReversed);
Servo_DeclarationBlock_SetCounterResetListItem(&EnsureDecls(), aValue,
aIsReversed);
}
// Set "counter-set: list-item <integer>".
void SetCounterSetListItem(int32_t aValue) {
Servo_DeclarationBlock_SetCounterSetListItem(mDecl, aValue);
Servo_DeclarationBlock_SetCounterSetListItem(&EnsureDecls(), aValue);
}
// Set a property to a pixel value
void SetPixelValue(nsCSSPropertyID aId, float aValue) {
Servo_DeclarationBlock_SetPixelValue(mDecl, aId, aValue);
Servo_DeclarationBlock_SetPixelValue(&EnsureDecls(), aId, aValue);
}
void SetPixelValueIfUnset(nsCSSPropertyID aId, float aValue) {
@ -125,18 +132,18 @@ class MappedDeclarations final {
void SetLengthValue(nsCSSPropertyID aId, const nsCSSValue& aValue) {
MOZ_ASSERT(aValue.IsLengthUnit());
Servo_DeclarationBlock_SetLengthValue(mDecl, aId, aValue.GetFloatValue(),
aValue.GetUnit());
Servo_DeclarationBlock_SetLengthValue(
&EnsureDecls(), aId, aValue.GetFloatValue(), aValue.GetUnit());
}
// Set a property to a number value
void SetNumberValue(nsCSSPropertyID aId, float aValue) {
Servo_DeclarationBlock_SetNumberValue(mDecl, aId, aValue);
Servo_DeclarationBlock_SetNumberValue(&EnsureDecls(), aId, aValue);
}
// Set a property to a percent value
void SetPercentValue(nsCSSPropertyID aId, float aValue) {
Servo_DeclarationBlock_SetPercentValue(mDecl, aId, aValue);
Servo_DeclarationBlock_SetPercentValue(&EnsureDecls(), aId, aValue);
}
void SetPercentValueIfUnset(nsCSSPropertyID aId, float aValue) {
@ -147,7 +154,7 @@ class MappedDeclarations final {
// Set a property to `auto`
void SetAutoValue(nsCSSPropertyID aId) {
Servo_DeclarationBlock_SetAutoValue(mDecl, aId);
Servo_DeclarationBlock_SetAutoValue(&EnsureDecls(), aId);
}
void SetAutoValueIfUnset(nsCSSPropertyID aId) {
@ -158,7 +165,7 @@ class MappedDeclarations final {
// Set a property to `currentcolor`
void SetCurrentColor(nsCSSPropertyID aId) {
Servo_DeclarationBlock_SetCurrentColor(mDecl, aId);
Servo_DeclarationBlock_SetCurrentColor(&EnsureDecls(), aId);
}
void SetCurrentColorIfUnset(nsCSSPropertyID aId) {
@ -169,7 +176,7 @@ class MappedDeclarations final {
// Set a property to an RGBA nscolor value
void SetColorValue(nsCSSPropertyID aId, nscolor aValue) {
Servo_DeclarationBlock_SetColorValue(mDecl, aId, aValue);
Servo_DeclarationBlock_SetColorValue(&EnsureDecls(), aId, aValue);
}
void SetColorValueIfUnset(nsCSSPropertyID aId, nscolor aValue) {
@ -180,26 +187,39 @@ class MappedDeclarations final {
// Set font-family to a string
void SetFontFamily(const nsACString& aValue) {
Servo_DeclarationBlock_SetFontFamily(mDecl, &aValue);
Servo_DeclarationBlock_SetFontFamily(&EnsureDecls(), &aValue);
}
// Add a quirks-mode override to the decoration color of elements nested in
// <a>
void SetTextDecorationColorOverride() {
Servo_DeclarationBlock_SetTextDecorationColorOverride(mDecl);
Servo_DeclarationBlock_SetTextDecorationColorOverride(&EnsureDecls());
}
void SetBackgroundImage(const nsAttrValue& value);
void SetAspectRatio(float aWidth, float aHeight) {
Servo_DeclarationBlock_SetAspectRatio(mDecl, aWidth, aHeight);
Servo_DeclarationBlock_SetAspectRatio(&EnsureDecls(), aWidth, aHeight);
}
const nsAttrValue* GetAttr(nsAtom* aName) {
MOZ_ASSERT(mElement.IsAttributeMapped(aName));
return mElement.GetParsedAttr(aName);
}
private:
dom::Document* const mDocument;
RefPtr<StyleLockedDeclarationBlock> mDecl;
StyleLockedDeclarationBlock& EnsureDecls() {
if (!mDecls) {
mDecls = Servo_DeclarationBlock_CreateEmpty().Consume();
}
return *mDecls;
}
dom::Document& mDocument;
dom::Element& mElement;
RefPtr<StyleLockedDeclarationBlock> mDecls;
};
} // namespace mozilla
#endif // mozilla_MappedDeclarations_h
#endif

View File

@ -34,7 +34,6 @@ headers = [
"mozilla/ServoTraversalStatistics.h",
"mozilla/SizeOfState.h",
"nsCSSProps.h",
"nsMappedAttributes.h",
"nsNameSpaceManager.h",
]
raw-lines = [

View File

@ -321,14 +321,6 @@ const ServoElementSnapshotTable& ServoStyleSet::Snapshots() {
return GetPresContext()->RestyleManager()->Snapshots();
}
void ServoStyleSet::ResolveMappedAttrDeclarationBlocks() {
if (AttributeStyles* attrStyles = mDocument->GetAttributeStyles()) {
attrStyles->CalculateMappedServoDeclarations();
}
mDocument->ResolveScheduledSVGPresAttrs();
}
void ServoStyleSet::PreTraverseSync() {
// Get the Document's root element to ensure that the cache is valid before
// calling into the (potentially-parallel) Servo traversal, where a cache hit
@ -341,7 +333,7 @@ void ServoStyleSet::PreTraverseSync() {
// can end up doing editing stuff, which adds stylesheets etc...
mDocument->FlushUserFontSet();
ResolveMappedAttrDeclarationBlocks();
mDocument->ResolveScheduledPresAttrs();
LookAndFeel::NativeInit();

View File

@ -552,14 +552,6 @@ class ServoStyleSet {
*/
const SnapshotTable& Snapshots();
/**
* Resolve all DeclarationBlocks attached to mapped
* presentation attributes cached on the document.
*
* Call this before jumping into Servo's style system.
*/
void ResolveMappedAttrDeclarationBlocks();
/**
* Clear our cached mNonInheritingComputedStyles.
*

View File

@ -81,7 +81,7 @@ EXPORTS.mozilla += [
"GlobalStyleSheetCache.h",
"ImportScanner.h",
"LayerAnimationInfo.h",
"MappedDeclarations.h",
"MappedDeclarationsBuilder.h",
"MediaFeatureChange.h",
"PostTraversalTask.h",
"PreferenceSheet.h",
@ -208,7 +208,7 @@ UNIFIED_SOURCES += [
"ImportScanner.cpp",
"LayerAnimationInfo.cpp",
"Loader.cpp",
"MappedDeclarations.cpp",
"MappedDeclarationsBuilder.cpp",
"MediaList.cpp",
"MediaQueryList.cpp",
"nsAnimationManager.cpp",

View File

@ -18,7 +18,7 @@
To change the list of properties, see ServoCSSPropList.h
*/
enum nsCSSPropertyID {
enum nsCSSPropertyID : int32_t {
eCSSProperty_UNKNOWN = -1,
$property_ids

View File

@ -175,16 +175,18 @@ nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
const nsCSSPropertyID aPropID, const SVGAnimatedLength& aLength) {
return SetSMILValueHelper([aPropID, &aLength](DeclarationBlock& aDecl) {
MOZ_ASSERT(aDecl.IsMutable());
return SVGElement::UpdateDeclarationBlockFromLength(
aDecl, aPropID, aLength, SVGElement::ValToUse::Anim);
*aDecl.Raw(), aPropID, aLength, SVGElement::ValToUse::Anim);
});
}
nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
const nsCSSPropertyID /*aPropID*/, const SVGAnimatedPathSegList& aPath) {
return SetSMILValueHelper([&aPath](DeclarationBlock& aDecl) {
MOZ_ASSERT(aDecl.IsMutable());
return SVGElement::UpdateDeclarationBlockFromPath(
aDecl, aPath, SVGElement::ValToUse::Anim);
*aDecl.Raw(), aPath, SVGElement::ValToUse::Anim);
});
}

View File

@ -589,40 +589,18 @@ impl<'le> GeckoElement<'le> {
}
#[inline(always)]
fn attrs(&self) -> Option<&structs::AttrArray_Impl> {
unsafe { self.0.mAttrs.mImpl.mPtr.as_ref() }
}
#[inline(always)]
fn non_mapped_attrs(&self) -> &[structs::AttrArray_InternalAttr] {
let attrs = match self.attrs() {
Some(attrs) => attrs,
None => return &[],
};
fn attrs(&self) -> &[structs::AttrArray_InternalAttr] {
unsafe {
attrs.mBuffer.as_slice(attrs.mAttrCount as usize)
}
}
#[inline(always)]
fn mapped_attrs(&self) -> &[structs::AttrArray_InternalAttr] {
let attrs = match self.attrs() {
Some(attrs) => attrs,
None => return &[],
};
unsafe {
let attrs = match attrs.mMappedAttrs.as_ref() {
Some(attrs) => attrs,
match self.0.mAttrs.mImpl.mPtr.as_ref() {
Some(attrs) => attrs.mBuffer.as_slice(attrs.mAttrCount as usize),
None => return &[],
};
attrs.mBuffer.as_slice(attrs.mAttrCount as usize)
}
}
}
#[inline]
fn iter_attrs(&self) -> impl Iterator<Item = &structs::AttrArray_InternalAttr> {
self.non_mapped_attrs().iter().chain(self.mapped_attrs().iter())
self.attrs().iter()
}
#[inline(always)]
@ -630,7 +608,7 @@ impl<'le> GeckoElement<'le> {
if !self.has_part_attr() {
return None;
}
snapshot_helpers::find_attr(self.non_mapped_attrs(), &atom!("part"))
snapshot_helpers::find_attr(self.attrs(), &atom!("part"))
}
#[inline(always)]
@ -646,7 +624,7 @@ impl<'le> GeckoElement<'le> {
}
}
snapshot_helpers::find_attr(self.non_mapped_attrs(), &atom!("class"))
snapshot_helpers::find_attr(self.attrs(), &atom!("class"))
}
#[inline]
@ -1054,7 +1032,7 @@ impl<'le> TElement for GeckoElement<'le> {
let slot: &structs::HTMLSlotElement = unsafe { mem::transmute(self.0) };
if cfg!(debug_assertions) {
let base: &RawGeckoElement = &slot._base._base._base._base;
let base: &RawGeckoElement = &slot._base._base._base;
assert_eq!(base as *const _, self.0 as *const _, "Bad cast");
}
@ -1198,7 +1176,7 @@ impl<'le> TElement for GeckoElement<'le> {
#[inline]
fn exports_any_part(&self) -> bool {
snapshot_helpers::find_attr(self.non_mapped_attrs(), &atom!("exportparts")).is_some()
snapshot_helpers::find_attr(self.attrs(), &atom!("exportparts")).is_some()
}
// FIXME(emilio): we should probably just return a reference to the Atom.
@ -1207,8 +1185,7 @@ impl<'le> TElement for GeckoElement<'le> {
if !self.has_id() {
return None;
}
snapshot_helpers::get_id(self.non_mapped_attrs())
snapshot_helpers::get_id(self.attrs())
}
fn each_attr_name<F>(&self, mut callback: F)
@ -1239,7 +1216,7 @@ impl<'le> TElement for GeckoElement<'le> {
where
F: FnMut(&AtomIdent),
{
snapshot_helpers::each_exported_part(self.non_mapped_attrs(), name, callback)
snapshot_helpers::each_exported_part(self.attrs(), name, callback)
}
fn each_part<F>(&self, callback: F)
@ -1793,7 +1770,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
fn assigned_slot(&self) -> Option<Self> {
let slot = self.extended_slots()?._base.mAssignedSlot.mRawPtr;
unsafe { Some(GeckoElement(&slot.as_ref()?._base._base._base._base)) }
unsafe { Some(GeckoElement(&slot.as_ref()?._base._base._base)) }
}
#[inline]
@ -1865,9 +1842,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
local_name: &LocalName,
operation: &AttrSelectorOperation<&AttrValue>,
) -> bool {
if self.attrs().is_none() {
return false;
}
snapshot_helpers::attr_matches(self.iter_attrs(), ns, local_name, operation)
}
@ -2074,7 +2048,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
return false;
}
let element_id = match snapshot_helpers::get_id(self.non_mapped_attrs()) {
let element_id = match snapshot_helpers::get_id(self.attrs()) {
Some(id) => id,
None => return false,
};
@ -2094,7 +2068,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
#[inline]
fn imported_part(&self, name: &AtomIdent) -> Option<AtomIdent> {
snapshot_helpers::imported_part(self.non_mapped_attrs(), name)
snapshot_helpers::imported_part(self.attrs(), name)
}
#[inline(always)]

View File

@ -1,6 +0,0 @@
[attributes.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[First set attribute is returned with mapped attribute set first]
bug: 1303629
expected: FAIL

View File

@ -2920,6 +2920,7 @@ var browserTests = [
"abc<font face=\"monospace\" size=\"7\" color=\"#ff0000\"><span style=\"background-color:rgb(0, 221, 221)\">[d]</span></font>ef",
"abc<font size=\"7\" color=\"#ff0000\" face=\"monospace\"><span style=\"background-color:rgb(0, 221, 221)\">[d]</span></font>ef",
"abc<font size=\"7\" face=\"monospace\" color=\"#ff0000\"><span style=\"background-color:rgb(0, 221, 221)\">[d]</span></font>ef",
"abc<font size=\"7\" color=\"#ff0000\" face=\"monospace\" style=\"background-color:rgb(0, 221, 221)\">[d]</font>ef",
"abc<font color=\"#ff0000\" face=\"monospace\" size=\"7\" style=\"background-color:rgb(0, 221, 221)\">[d]</font>ef",
"abc<font color=\"#ff0000\" size=\"7\" face=\"monospace\" style=\"background-color:rgb(0, 221, 221)\">[d]</font>ef",
"abc<font face=\"monospace\" color=\"#ff0000\" size=\"7\" style=\"background-color:rgb(0, 221, 221)\">[d]</font>ef",