summaryrefslogtreecommitdiff
path: root/dom
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2020-04-17 05:07:41 -0400
committerMatt A. Tobin <email@mattatobin.com>2020-04-17 05:07:41 -0400
commit5f297c5f57583b0f9d27d714beb285919f42d655 (patch)
treef67fd1bafe4c449fc6527e172deb59411bfbf85f /dom
parentf07f8aecb8a03d33d0b90d685d85960a29543c75 (diff)
downloaduxp-5f297c5f57583b0f9d27d714beb285919f42d655.tar.gz
Issue #1375 - Include content rules from HTMLTableCellElement::WalkContentStyleRules and move to the mapped attr functionality
* Bugs 1341647 and 1341648
Diffstat (limited to 'dom')
-rw-r--r--dom/base/nsAttrAndChildArray.cpp13
-rw-r--r--dom/base/nsAttrAndChildArray.h6
-rw-r--r--dom/base/nsFrameLoader.cpp3
-rw-r--r--dom/base/nsMappedAttributes.cpp12
-rw-r--r--dom/html/HTMLBodyElement.cpp237
-rw-r--r--dom/html/HTMLBodyElement.h36
-rw-r--r--dom/html/HTMLTableCellElement.cpp14
-rw-r--r--dom/html/HTMLTableCellElement.h2
-rw-r--r--dom/html/HTMLTableElement.cpp27
-rw-r--r--dom/html/HTMLTableElement.h4
-rw-r--r--dom/html/reftests/body-frame-margin-remove-other-pres-hint-ref.html14
-rw-r--r--dom/html/reftests/body-frame-margin-remove-other-pres-hint.html16
-rw-r--r--dom/html/reftests/body-topmargin-dynamic.html12
-rw-r--r--dom/html/reftests/body-topmargin-ref.html7
-rw-r--r--dom/html/reftests/reftest-stylo.list7
-rw-r--r--dom/html/reftests/reftest.list7
16 files changed, 158 insertions, 259 deletions
diff --git a/dom/base/nsAttrAndChildArray.cpp b/dom/base/nsAttrAndChildArray.cpp
index 9fd27262b3..4daac498ba 100644
--- a/dom/base/nsAttrAndChildArray.cpp
+++ b/dom/base/nsAttrAndChildArray.cpp
@@ -714,10 +714,19 @@ nsAttrAndChildArray::MappedAttrCount() const
return mImpl && mImpl->mMappedAttrs ? (uint32_t)mImpl->mMappedAttrs->Count() : 0;
}
+nsresult
+nsAttrAndChildArray::ForceMapped(nsMappedAttributeElement* aContent, nsIDocument* aDocument)
+{
+ nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet();
+ RefPtr<nsMappedAttributes> mapped = GetModifiableMapped(aContent, sheet, false, 0);
+ return MakeMappedUnique(mapped);
+}
+
nsMappedAttributes*
nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent,
nsHTMLStyleSheet* aSheet,
- bool aWillAddAttr)
+ bool aWillAddAttr,
+ int32_t aAttrCount)
{
if (mImpl && mImpl->mMappedAttrs) {
return mImpl->mMappedAttrs->Clone(aWillAddAttr);
@@ -727,7 +736,7 @@ nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent,
nsMapRuleToAttributesFunc mapRuleFunc =
aContent->GetAttributeMappingFunction();
- return new nsMappedAttributes(aSheet, mapRuleFunc);
+ return new (aAttrCount) nsMappedAttributes(aSheet, mapRuleFunc);
}
nsresult
diff --git a/dom/base/nsAttrAndChildArray.h b/dom/base/nsAttrAndChildArray.h
index f34370c43d..ffbad196c5 100644
--- a/dom/base/nsAttrAndChildArray.h
+++ b/dom/base/nsAttrAndChildArray.h
@@ -135,6 +135,9 @@ public:
return MappedAttrCount();
}
+ // Force this to have mapped attributes, even if those attributes are empty.
+ nsresult ForceMapped(nsMappedAttributeElement* aContent, nsIDocument* aDocument);
+
private:
nsAttrAndChildArray(const nsAttrAndChildArray& aOther) = delete;
nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) = delete;
@@ -148,7 +151,8 @@ private:
nsMappedAttributes*
GetModifiableMapped(nsMappedAttributeElement* aContent,
nsHTMLStyleSheet* aSheet,
- bool aWillAddAttr);
+ bool aWillAddAttr,
+ int32_t aAttrCount = 1);
nsresult MakeMappedUnique(nsMappedAttributes* aAttributes);
uint32_t AttrSlotsSize() const
diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp
index 2804f2d4c0..942a841025 100644
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -57,6 +57,7 @@
#include "nsGlobalWindow.h"
#include "nsPIWindowRoot.h"
#include "nsLayoutUtils.h"
+#include "nsMappedAttributes.h"
#include "nsView.h"
#include "GroupedSHistory.h"
#include "PartialSHistory.h"
@@ -936,6 +937,8 @@ nsFrameLoader::MarginsChanged(uint32_t aMarginWidth,
RefPtr<nsPresContext> presContext;
mDocShell->GetPresContext(getter_AddRefs(presContext));
if (presContext)
+ // rebuild, because now the same nsMappedAttributes* will produce
+ // a different style
presContext->RebuildAllStyleData(nsChangeHint(0), eRestyle_Subtree);
}
diff --git a/dom/base/nsMappedAttributes.cpp b/dom/base/nsMappedAttributes.cpp
index a3accd2a76..9e80c94df6 100644
--- a/dom/base/nsMappedAttributes.cpp
+++ b/dom/base/nsMappedAttributes.cpp
@@ -62,11 +62,17 @@ nsMappedAttributes::Clone(bool aWillAddAttr)
void* nsMappedAttributes::operator new(size_t aSize, uint32_t aAttrCount) CPP_THROW_NEW
{
- NS_ASSERTION(aAttrCount > 0, "zero-attribute nsMappedAttributes requested");
+ size_t size = aSize + aAttrCount * sizeof(InternalAttr);
// aSize will include the mAttrs buffer so subtract that.
- void* newAttrs = ::operator new(aSize - sizeof(void*[1]) +
- aAttrCount * sizeof(InternalAttr));
+ // We don't want to under-allocate, however, so do not subtract
+ // if we have zero attributes. The zero attribute case only happens
+ // for <body>'s mapped attributes
+ if (aAttrCount != 0) {
+ size -= sizeof(void*[1]);
+ }
+
+ void* newAttrs = ::operator new(size);
#ifdef DEBUG
static_cast<nsMappedAttributes*>(newAttrs)->mBufferSize = aAttrCount;
diff --git a/dom/html/HTMLBodyElement.cpp b/dom/html/HTMLBodyElement.cpp
index 6230cb6ca0..f70e203897 100644
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -27,180 +27,8 @@ namespace dom {
//----------------------------------------------------------------------
-BodyRule::BodyRule(HTMLBodyElement* aPart)
- : mPart(aPart)
-{
-}
-
-BodyRule::~BodyRule()
-{
-}
-
-NS_IMPL_ISUPPORTS(BodyRule, nsIStyleRule)
-
-/* virtual */ void
-BodyRule::MapRuleInfoInto(nsRuleData* aData)
-{
- if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)) || !mPart)
- return; // We only care about margins.
-
- int32_t bodyMarginWidth = -1;
- int32_t bodyMarginHeight = -1;
- int32_t bodyTopMargin = -1;
- int32_t bodyBottomMargin = -1;
- int32_t bodyLeftMargin = -1;
- int32_t bodyRightMargin = -1;
-
- // check the mode (fortunately, the ruleData has a presContext for us to use!)
- NS_ASSERTION(aData->mPresContext, "null presContext in ruleNode was unexpected");
- nsCompatibility mode = aData->mPresContext->CompatibilityMode();
-
-
- const nsAttrValue* value;
- if (mPart->GetAttrCount() > 0) {
- // if marginwidth/marginheight are set, reflect them as 'margin'
- value = mPart->GetParsedAttr(nsGkAtoms::marginwidth);
- if (value && value->Type() == nsAttrValue::eInteger) {
- bodyMarginWidth = value->GetIntegerValue();
- if (bodyMarginWidth < 0) bodyMarginWidth = 0;
- nsCSSValue* marginLeft = aData->ValueForMarginLeft();
- if (marginLeft->GetUnit() == eCSSUnit_Null)
- marginLeft->SetFloatValue((float)bodyMarginWidth, eCSSUnit_Pixel);
- nsCSSValue* marginRight = aData->ValueForMarginRight();
- if (marginRight->GetUnit() == eCSSUnit_Null)
- marginRight->SetFloatValue((float)bodyMarginWidth, eCSSUnit_Pixel);
- }
-
- value = mPart->GetParsedAttr(nsGkAtoms::marginheight);
- if (value && value->Type() == nsAttrValue::eInteger) {
- bodyMarginHeight = value->GetIntegerValue();
- if (bodyMarginHeight < 0) bodyMarginHeight = 0;
- nsCSSValue* marginTop = aData->ValueForMarginTop();
- if (marginTop->GetUnit() == eCSSUnit_Null)
- marginTop->SetFloatValue((float)bodyMarginHeight, eCSSUnit_Pixel);
- nsCSSValue* marginBottom = aData->ValueForMarginBottom();
- if (marginBottom->GetUnit() == eCSSUnit_Null)
- marginBottom->SetFloatValue((float)bodyMarginHeight, eCSSUnit_Pixel);
- }
-
- // topmargin (IE-attribute)
- value = mPart->GetParsedAttr(nsGkAtoms::topmargin);
- if (value && value->Type() == nsAttrValue::eInteger) {
- bodyTopMargin = value->GetIntegerValue();
- if (bodyTopMargin < 0) bodyTopMargin = 0;
- nsCSSValue* marginTop = aData->ValueForMarginTop();
- if (marginTop->GetUnit() == eCSSUnit_Null)
- marginTop->SetFloatValue((float)bodyTopMargin, eCSSUnit_Pixel);
- }
-
- // bottommargin (IE-attribute)
- value = mPart->GetParsedAttr(nsGkAtoms::bottommargin);
- if (value && value->Type() == nsAttrValue::eInteger) {
- bodyBottomMargin = value->GetIntegerValue();
- if (bodyBottomMargin < 0) bodyBottomMargin = 0;
- nsCSSValue* marginBottom = aData->ValueForMarginBottom();
- if (marginBottom->GetUnit() == eCSSUnit_Null)
- marginBottom->SetFloatValue((float)bodyBottomMargin, eCSSUnit_Pixel);
- }
-
- // leftmargin (IE-attribute)
- value = mPart->GetParsedAttr(nsGkAtoms::leftmargin);
- if (value && value->Type() == nsAttrValue::eInteger) {
- bodyLeftMargin = value->GetIntegerValue();
- if (bodyLeftMargin < 0) bodyLeftMargin = 0;
- nsCSSValue* marginLeft = aData->ValueForMarginLeft();
- if (marginLeft->GetUnit() == eCSSUnit_Null)
- marginLeft->SetFloatValue((float)bodyLeftMargin, eCSSUnit_Pixel);
- }
-
- // rightmargin (IE-attribute)
- value = mPart->GetParsedAttr(nsGkAtoms::rightmargin);
- if (value && value->Type() == nsAttrValue::eInteger) {
- bodyRightMargin = value->GetIntegerValue();
- if (bodyRightMargin < 0) bodyRightMargin = 0;
- nsCSSValue* marginRight = aData->ValueForMarginRight();
- if (marginRight->GetUnit() == eCSSUnit_Null)
- marginRight->SetFloatValue((float)bodyRightMargin, eCSSUnit_Pixel);
- }
-
- }
-
- // 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) {
- nsCOMPtr<nsIDocShell> docShell(aData->mPresContext->GetDocShell());
- if (docShell) {
- nscoord frameMarginWidth=-1; // default value
- nscoord frameMarginHeight=-1; // default value
- docShell->GetMarginWidth(&frameMarginWidth); // -1 indicates not set
- docShell->GetMarginHeight(&frameMarginHeight);
- if ((frameMarginWidth >= 0) && (bodyMarginWidth == -1)) { // set in <frame> & not in <body>
- if (eCompatibility_NavQuirks == mode) {
- if ((bodyMarginHeight == -1) && (0 > frameMarginHeight)) // nav quirk
- frameMarginHeight = 0;
- }
- }
- if ((frameMarginHeight >= 0) && (bodyMarginHeight == -1)) { // set in <frame> & not in <body>
- if (eCompatibility_NavQuirks == mode) {
- if ((bodyMarginWidth == -1) && (0 > frameMarginWidth)) // nav quirk
- frameMarginWidth = 0;
- }
- }
-
- if ((bodyMarginWidth == -1) && (frameMarginWidth >= 0)) {
- nsCSSValue* marginLeft = aData->ValueForMarginLeft();
- if (marginLeft->GetUnit() == eCSSUnit_Null)
- marginLeft->SetFloatValue((float)frameMarginWidth, eCSSUnit_Pixel);
- nsCSSValue* marginRight = aData->ValueForMarginRight();
- if (marginRight->GetUnit() == eCSSUnit_Null)
- marginRight->SetFloatValue((float)frameMarginWidth, eCSSUnit_Pixel);
- }
-
- if ((bodyMarginHeight == -1) && (frameMarginHeight >= 0)) {
- nsCSSValue* marginTop = aData->ValueForMarginTop();
- if (marginTop->GetUnit() == eCSSUnit_Null)
- marginTop->SetFloatValue((float)frameMarginHeight, eCSSUnit_Pixel);
- nsCSSValue* marginBottom = aData->ValueForMarginBottom();
- if (marginBottom->GetUnit() == eCSSUnit_Null)
- marginBottom->SetFloatValue((float)frameMarginHeight, eCSSUnit_Pixel);
- }
- }
- }
-}
-
-/* virtual */ bool
-BodyRule::MightMapInheritedStyleData()
-{
- return false;
-}
-
-/* virtual */ bool
-BodyRule::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
- nsCSSValue* aValue)
-{
- MOZ_ASSERT(false, "GetDiscretelyAnimatedCSSValue is not implemented yet");
- return false;
-}
-
-#ifdef DEBUG
-/* virtual */ void
-BodyRule::List(FILE* out, int32_t aIndent) const
-{
- nsAutoCString indent;
- for (int32_t index = aIndent; --index >= 0; ) {
- indent.AppendLiteral(" ");
- }
- fprintf_stderr(out, "%s[body rule] {}\n", indent.get());
-}
-#endif
-
-//----------------------------------------------------------------------
-
HTMLBodyElement::~HTMLBodyElement()
{
- if (mContentStyleRule) {
- mContentStyleRule->mPart = nullptr;
- }
}
JSObject*
@@ -348,17 +176,6 @@ HTMLBodyElement::ParseAttribute(int32_t aNamespaceID,
}
void
-HTMLBodyElement::UnbindFromTree(bool aDeep, bool aNullParent)
-{
- if (mContentStyleRule) {
- mContentStyleRule->mPart = nullptr;
- mContentStyleRule = nullptr;
- }
-
- nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
-}
-
-void
HTMLBodyElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
nsRuleData* aData)
{
@@ -413,22 +230,6 @@ HTMLBodyElement::GetAttributeMappingFunction() const
return &MapAttributesIntoRule;
}
-NS_IMETHODIMP
-HTMLBodyElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
-{
- nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
-
- if (!mContentStyleRule && IsInUncomposedDoc()) {
- // XXXbz should this use OwnerDoc() or GetComposedDoc()?
- // sXBL/XBL2 issue!
- mContentStyleRule = new BodyRule(this);
- }
- if (aRuleWalker && mContentStyleRule) {
- aRuleWalker->Forward(mContentStyleRule);
- }
- return NS_OK;
-}
-
NS_IMETHODIMP_(bool)
HTMLBodyElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
@@ -437,12 +238,12 @@ HTMLBodyElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{ &nsGkAtoms::vlink },
{ &nsGkAtoms::alink },
{ &nsGkAtoms::text },
- // These aren't mapped through attribute mapping, but they are
- // mapped through a style rule, so it is attribute dependent style.
- // XXXldb But we don't actually replace the body rule when we have
- // dynamic changes...
{ &nsGkAtoms::marginwidth },
{ &nsGkAtoms::marginheight },
+ { &nsGkAtoms::topmargin },
+ { &nsGkAtoms::rightmargin },
+ { &nsGkAtoms::bottommargin },
+ { &nsGkAtoms::leftmargin },
{ nullptr },
};
@@ -491,6 +292,36 @@ HTMLBodyElement::IsEventAttributeName(nsIAtom *aName)
EventNameType_HTMLBodyOrFramesetOnly);
}
+nsresult
+HTMLBodyElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+ nsIContent* aBindingParent,
+ bool aCompileEventHandlers)
+{
+ nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
+ aBindingParent,
+ aCompileEventHandlers);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return mAttrsAndChildren.ForceMapped(this, OwnerDoc());
+}
+
+nsresult
+HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValue* aValue,
+ bool aNotify)
+{
+ nsresult rv = nsGenericHTMLElement::AfterSetAttr(aNameSpaceID,
+ aName, aValue, aNotify);
+ NS_ENSURE_SUCCESS(rv, rv);
+ // if the last mapped attribute was removed, don't clear the
+ // nsMappedAttributes, our style can still depend on the containing frame element
+ if (!aValue && IsAttributeMapped(aName)) {
+ nsresult rv = mAttrsAndChildren.ForceMapped(this, OwnerDoc());
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+}
+
#define EVENT(name_, id_, type_, struct_) /* nothing; handled by the superclass */
// nsGenericHTMLElement::GetOnError returns
// already_AddRefed<EventHandlerNonNull> while other getters return
diff --git a/dom/html/HTMLBodyElement.h b/dom/html/HTMLBodyElement.h
index 436dc4cba3..ad1f5d8721 100644
--- a/dom/html/HTMLBodyElement.h
+++ b/dom/html/HTMLBodyElement.h
@@ -15,28 +15,6 @@ namespace mozilla {
namespace dom {
class OnBeforeUnloadEventHandlerNonNull;
-class HTMLBodyElement;
-
-class BodyRule: public nsIStyleRule
-{
- virtual ~BodyRule();
-
-public:
- explicit BodyRule(HTMLBodyElement* aPart);
-
- NS_DECL_ISUPPORTS
-
- // nsIStyleRule interface
- virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
- virtual bool MightMapInheritedStyleData() override;
- virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
- nsCSSValue* aValue) override;
-#ifdef DEBUG
- virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
-#endif
-
- HTMLBodyElement* mPart; // not ref-counted, cleared by content
-};
class HTMLBodyElement final : public nsGenericHTMLElement,
public nsIDOMHTMLBodyElement
@@ -125,23 +103,27 @@ public:
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult) override;
- virtual void UnbindFromTree(bool aDeep = true,
- bool aNullParent = true) override;
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
- NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
virtual already_AddRefed<nsIEditor> GetAssociatedEditor() override;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
virtual bool IsEventAttributeName(nsIAtom* aName) override;
+ virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+ nsIContent* aBindingParent,
+ bool aCompileEventHandlers) override;
+ /**
+ * Called when an attribute has just been changed
+ */
+ virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAttrValue* aValue, bool aNotify) override;
+
protected:
virtual ~HTMLBodyElement();
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
- RefPtr<BodyRule> mContentStyleRule;
-
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
nsRuleData* aData);
diff --git a/dom/html/HTMLTableCellElement.cpp b/dom/html/HTMLTableCellElement.cpp
index 1cf413413c..e8b338342d 100644
--- a/dom/html/HTMLTableCellElement.cpp
+++ b/dom/html/HTMLTableCellElement.cpp
@@ -107,9 +107,7 @@ HTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
nsresult rv = nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
NS_ENSURE_SUCCESS(rv, rv);
- if (HTMLTableElement* table = GetTable()) {
- nsMappedAttributes* tableInheritedAttributes =
- table->GetAttributesMappedForCell();
+ if (nsMappedAttributes* tableInheritedAttributes = GetMappedAttributesInheritedFromTable()) {
if (tableInheritedAttributes) {
aRuleWalker->Forward(tableInheritedAttributes);
}
@@ -117,6 +115,16 @@ HTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
return NS_OK;
}
+nsMappedAttributes*
+HTMLTableCellElement::GetMappedAttributesInheritedFromTable() const
+{
+ if (HTMLTableElement* table = GetTable()) {
+ return table->GetAttributesMappedForCell();
+ }
+
+ return nullptr;
+}
+
NS_IMETHODIMP
HTMLTableCellElement::SetAbbr(const nsAString& aAbbr)
{
diff --git a/dom/html/HTMLTableCellElement.h b/dom/html/HTMLTableCellElement.h
index ab7a918eb9..6740b870ed 100644
--- a/dom/html/HTMLTableCellElement.h
+++ b/dom/html/HTMLTableCellElement.h
@@ -148,6 +148,8 @@ public:
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
+ // Get mapped attributes of ancestor table, if any
+ nsMappedAttributes* GetMappedAttributesInheritedFromTable() const;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
diff --git a/dom/html/HTMLTableElement.cpp b/dom/html/HTMLTableElement.cpp
index 5784fa6912..df84a0f77d 100644
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -322,7 +322,7 @@ TableRowsCollection::ParentDestroyed()
HTMLTableElement::HTMLTableElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsGenericHTMLElement(aNodeInfo),
- mTableInheritedAttributes(TABLE_ATTRS_DIRTY)
+ mTableInheritedAttributes(nullptr)
{
SetHasWeirdParserInsertionMode();
}
@@ -912,20 +912,15 @@ MapInheritedTableAttributesIntoRule(const nsMappedAttributes* aAttributes,
nsMappedAttributes*
HTMLTableElement::GetAttributesMappedForCell()
{
- if (mTableInheritedAttributes) {
- if (mTableInheritedAttributes == TABLE_ATTRS_DIRTY)
- BuildInheritedAttributes();
- if (mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
- return mTableInheritedAttributes;
- }
- return nullptr;
+ return mTableInheritedAttributes;
}
void
HTMLTableElement::BuildInheritedAttributes()
{
- NS_ASSERTION(mTableInheritedAttributes == TABLE_ATTRS_DIRTY,
+ NS_ASSERTION(!mTableInheritedAttributes,
"potential leak, plus waste of work");
+ MOZ_ASSERT(NS_IsMainThread());
nsIDocument *document = GetComposedDoc();
nsHTMLStyleSheet* sheet = document ?
document->GetAttributeStyleSheet() : nullptr;
@@ -960,10 +955,7 @@ HTMLTableElement::BuildInheritedAttributes()
void
HTMLTableElement::ReleaseInheritedAttributes()
{
- if (mTableInheritedAttributes &&
- mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
- NS_RELEASE(mTableInheritedAttributes);
- mTableInheritedAttributes = TABLE_ATTRS_DIRTY;
+ NS_IF_RELEASE(mTableInheritedAttributes);
}
nsresult
@@ -972,9 +964,12 @@ HTMLTableElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
bool aCompileEventHandlers)
{
ReleaseInheritedAttributes();
- return nsGenericHTMLElement::BindToTree(aDocument, aParent,
- aBindingParent,
- aCompileEventHandlers);
+ nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
+ aBindingParent,
+ aCompileEventHandlers);
+ NS_ENSURE_SUCCESS(rv, rv);
+ BuildInheritedAttributes();
+ return NS_OK;
}
void
diff --git a/dom/html/HTMLTableElement.h b/dom/html/HTMLTableElement.h
index cf83c9440d..0e907cf54f 100644
--- a/dom/html/HTMLTableElement.h
+++ b/dom/html/HTMLTableElement.h
@@ -14,8 +14,6 @@
namespace mozilla {
namespace dom {
-#define TABLE_ATTRS_DIRTY ((nsMappedAttributes*)0x1)
-
class TableRowsCollection;
class HTMLTableElement final : public nsGenericHTMLElement
@@ -220,8 +218,6 @@ protected:
RefPtr<nsContentList> mTBodies;
RefPtr<TableRowsCollection> mRows;
- // Sentinel value of TABLE_ATTRS_DIRTY indicates that this is dirty and needs
- // to be recalculated.
nsMappedAttributes *mTableInheritedAttributes;
void BuildInheritedAttributes();
void ReleaseInheritedAttributes();
diff --git a/dom/html/reftests/body-frame-margin-remove-other-pres-hint-ref.html b/dom/html/reftests/body-frame-margin-remove-other-pres-hint-ref.html
new file mode 100644
index 0000000000..8446d7f260
--- /dev/null
+++ b/dom/html/reftests/body-frame-margin-remove-other-pres-hint-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <title></title>
+</head>
+<body>
+<script type="text/javascript">
+ function loadFrame() {
+ document.documentElement.className = "";
+ }
+</script>
+<iframe id=frame onload="loadFrame()" src="data:text/html,<body><span lang='en'>text</span></body>" marginwidth="100px" marginheight="100px" width=300px height=300px></iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/dom/html/reftests/body-frame-margin-remove-other-pres-hint.html b/dom/html/reftests/body-frame-margin-remove-other-pres-hint.html
new file mode 100644
index 0000000000..6f49536376
--- /dev/null
+++ b/dom/html/reftests/body-frame-margin-remove-other-pres-hint.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <title></title>
+</head>
+<body>
+<script type="text/javascript">
+ function loadFrame() {
+ let frame = document.getElementById('frame');
+ frame.contentDocument.body.removeAttribute('lang');
+ document.documentElement.className = "";
+ }
+</script>
+<iframe id=frame onload="loadFrame()" src="data:text/html,<body lang='en'>text</body>" marginwidth="100px" marginheight="100px" width=300px height=300px></iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/dom/html/reftests/body-topmargin-dynamic.html b/dom/html/reftests/body-topmargin-dynamic.html
new file mode 100644
index 0000000000..e6c8c505e7
--- /dev/null
+++ b/dom/html/reftests/body-topmargin-dynamic.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+this text should have a margin of 100px on the top and left
+<p style="direction: rtl">this text should have a margin of 100px on the right</p>
+<script type="text/javascript">
+ document.body.setAttribute("topmargin", "100px");
+ document.body.setAttribute("leftmargin", "100px");
+ document.body.setAttribute("rightmargin", "100px");
+</script>
+</body>
+</html>
diff --git a/dom/html/reftests/body-topmargin-ref.html b/dom/html/reftests/body-topmargin-ref.html
new file mode 100644
index 0000000000..6530a0ae4b
--- /dev/null
+++ b/dom/html/reftests/body-topmargin-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<body topmargin="100px" leftmargin="100px" rightmargin="100px">
+this text should have a margin of 100px on the top and left
+<p style="direction: rtl">this text should have a margin of 100px on the right</p>
+</body>
+</html>
diff --git a/dom/html/reftests/reftest-stylo.list b/dom/html/reftests/reftest-stylo.list
index dd6339edf8..570c073587 100644
--- a/dom/html/reftests/reftest-stylo.list
+++ b/dom/html/reftests/reftest-stylo.list
@@ -64,3 +64,10 @@ pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784
# Test video with rotation information can be rotated.
== bug1228601-video-rotation-90.html bug1228601-video-rotation-90.html
+
+# Test that dynamically setting body margin attributes updates style appropriately
+== body-topmargin-dynamic.html body-topmargin-dynamic.html
+
+# Test that dynamically removing a nonmargin mapped attribute does not
+# destroy margins inherited from the frame.
+== body-frame-margin-remove-other-pres-hint.html body-frame-margin-remove-other-pres-hint.html
diff --git a/dom/html/reftests/reftest.list b/dom/html/reftests/reftest.list
index 27a13e7c92..82e773abb5 100644
--- a/dom/html/reftests/reftest.list
+++ b/dom/html/reftests/reftest.list
@@ -62,3 +62,10 @@ pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784
# Test video with rotation information can be rotated.
== bug1228601-video-rotation-90.html bug1228601-video-rotated-ref.html
+
+# Test that dynamically setting body margin attributes updates style appropriately
+== body-topmargin-dynamic.html body-topmargin-ref.html
+
+# Test that dynamically removing a nonmargin mapped attribute does not
+# destroy margins inherited from the frame.
+== body-frame-margin-remove-other-pres-hint.html body-frame-margin-remove-other-pres-hint-ref.html