diff --git a/dom/base/ShadowRoot.h b/dom/base/ShadowRoot.h index 775eaae957..63535c9a06 100644 --- a/dom/base/ShadowRoot.h +++ b/dom/base/ShadowRoot.h @@ -108,6 +108,7 @@ public: void SetInsertionPointChanged() { mInsertionPointChanged = true; } + nsXBLBinding* GetAssociatedBinding() { return mAssociatedBinding; } void SetAssociatedBinding(nsXBLBinding* aBinding) { mAssociatedBinding = aBinding; } JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; diff --git a/dom/base/nsAttrAndChildArray.cpp b/dom/base/nsAttrAndChildArray.cpp index 7ec5cebf01..23b0bf7e95 100644 --- a/dom/base/nsAttrAndChildArray.cpp +++ b/dom/base/nsAttrAndChildArray.cpp @@ -718,19 +718,10 @@ 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 mapped = GetModifiableMapped(aContent, sheet, false, 0); - return MakeMappedUnique(mapped); -} - nsMappedAttributes* nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent, nsHTMLStyleSheet* aSheet, - bool aWillAddAttr, - int32_t aAttrCount) + bool aWillAddAttr) { if (mImpl && mImpl->mMappedAttrs) { return mImpl->mMappedAttrs->Clone(aWillAddAttr); @@ -740,7 +731,7 @@ nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent, nsMapRuleToAttributesFunc mapRuleFunc = aContent->GetAttributeMappingFunction(); - return new (aAttrCount) nsMappedAttributes(aSheet, mapRuleFunc); + return new nsMappedAttributes(aSheet, mapRuleFunc); } nsresult diff --git a/dom/base/nsAttrAndChildArray.h b/dom/base/nsAttrAndChildArray.h index af12fba47b..0a6db7a5f3 100644 --- a/dom/base/nsAttrAndChildArray.h +++ b/dom/base/nsAttrAndChildArray.h @@ -144,9 +144,6 @@ 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; @@ -160,8 +157,7 @@ private: nsMappedAttributes* GetModifiableMapped(nsMappedAttributeElement* aContent, nsHTMLStyleSheet* aSheet, - bool aWillAddAttr, - int32_t aAttrCount = 1); + bool aWillAddAttr); nsresult MakeMappedUnique(nsMappedAttributes* aAttributes); uint32_t AttrSlotsSize() const diff --git a/dom/base/nsDOMMutationObserver.h b/dom/base/nsDOMMutationObserver.h index 6e17e4f2cc..1e2225d020 100644 --- a/dom/base/nsDOMMutationObserver.h +++ b/dom/base/nsDOMMutationObserver.h @@ -25,6 +25,7 @@ #include "nsIDocument.h" #include "mozilla/dom/Animation.h" #include "nsIAnimationObserver.h" +#include "nsGlobalWindow.h" class nsDOMMutationObserver; using mozilla::dom::MutationObservingInfo; @@ -599,11 +600,7 @@ protected: bool Suppressed() { - if (mOwner) { - nsCOMPtr d = mOwner->GetExtantDoc(); - return d && d->IsInSyncOperation(); - } - return false; + return mOwner && nsGlobalWindow::Cast(mOwner)->IsInSyncOperation(); } static void HandleMutationsInternal(mozilla::AutoSlowOperation& aAso); diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index c4ecff5c8c..33ddb08109 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -56,7 +56,6 @@ #include "nsGlobalWindow.h" #include "nsPIWindowRoot.h" #include "nsLayoutUtils.h" -#include "nsMappedAttributes.h" #include "nsView.h" #include "GroupedSHistory.h" #include "PartialSHistory.h" @@ -936,8 +935,6 @@ nsFrameLoader::MarginsChanged(uint32_t aMarginWidth, RefPtr 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/nsGkAtomList.h b/dom/base/nsGkAtomList.h index 1e9d870594..75c031afac 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -1134,6 +1134,7 @@ GK_ATOM(scrollbarDownBottom, "scrollbar-down-bottom") GK_ATOM(scrollbarDownTop, "scrollbar-down-top") GK_ATOM(scrollbarUpBottom, "scrollbar-up-bottom") GK_ATOM(scrollbarUpTop, "scrollbar-up-top") +GK_ATOM(scrollbarwidth, "scrollbarwidth") GK_ATOM(scrollbox, "scrollbox") GK_ATOM(scrollcorner, "scrollcorner") GK_ATOM(scrolling, "scrolling") diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 00ac023fce..e42835a0b2 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -1224,6 +1224,12 @@ public: already_AddRefed GetWindowRoot(mozilla::ErrorResult& aError); mozilla::dom::Performance* GetPerformance(); + + virtual bool IsInSyncOperation() override + { + return GetExtantDoc() && GetExtantDoc()->IsInSyncOperation(); + } + protected: // Web IDL helpers diff --git a/dom/base/nsIGlobalObject.cpp b/dom/base/nsIGlobalObject.cpp index 8923865082..7a6bab8b4b 100644 --- a/dom/base/nsIGlobalObject.cpp +++ b/dom/base/nsIGlobalObject.cpp @@ -4,10 +4,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsIGlobalObject.h" + +#include "mozilla/CycleCollectedJSContext.h" +#include "mozilla/dom/FunctionBinding.h" #include "nsContentUtils.h" #include "nsThreadUtils.h" #include "nsHostObjectProtocolHandler.h" +using mozilla::AutoSlowOperation; +using mozilla::CycleCollectedJSContext; +using mozilla::ErrorResult; +using mozilla::IgnoredErrorResult; +using mozilla::MicroTaskRunnable; +using mozilla::dom::VoidFunction; + nsIGlobalObject::~nsIGlobalObject() { UnlinkHostObjectURIs(); @@ -110,3 +120,31 @@ nsIGlobalObject::TraverseHostObjectURIs(nsCycleCollectionTraversalCallback &aCb) nsHostObjectProtocolHandler::Traverse(mHostObjectURIs[index], aCb); } } + +class QueuedMicrotask : public MicroTaskRunnable { + public: + QueuedMicrotask(nsIGlobalObject* aGlobal, VoidFunction& aCallback) + : mGlobal(aGlobal) + , mCallback(&aCallback) + {} + + /* unsafe */ + void Run(AutoSlowOperation& aAso) final { + IgnoredErrorResult rv; + mCallback->Call(static_cast(rv)); + } + + bool Suppressed() final { return mGlobal->IsInSyncOperation(); } + + private: + nsCOMPtr mGlobal; + RefPtr mCallback; +}; + +void nsIGlobalObject::QueueMicrotask(VoidFunction& aCallback) { + CycleCollectedJSContext* context = CycleCollectedJSContext::Get(); + if (context) { + RefPtr mt = new QueuedMicrotask(this, aCallback); + context->DispatchMicroTaskRunnable(mt.forget()); + } +} \ No newline at end of file diff --git a/dom/base/nsIGlobalObject.h b/dom/base/nsIGlobalObject.h index 6dfae4fbe4..1438803317 100644 --- a/dom/base/nsIGlobalObject.h +++ b/dom/base/nsIGlobalObject.h @@ -19,6 +19,13 @@ class nsCString; class nsCycleCollectionTraversalCallback; class nsIPrincipal; +namespace mozilla{ +namespace dom{ +class VoidFunction; +} +} + + class nsIGlobalObject : public nsISupports { nsTArray mHostObjectURIs; @@ -72,6 +79,10 @@ public: void UnlinkHostObjectURIs(); void TraverseHostObjectURIs(nsCycleCollectionTraversalCallback &aCb); + virtual bool IsInSyncOperation() { return false; } + + void QueueMicrotask(mozilla::dom::VoidFunction& aCallback); + protected: virtual ~nsIGlobalObject(); diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h index 1599a0094f..1d580540f8 100644 --- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h @@ -1652,6 +1652,9 @@ private: ParserHasNotified, // Sets if the node is apz aware or we have apz aware listeners. MayBeApzAware, + // Set if this node has at some point (and may still have) + // display:none or display:contents children. + NodeMayHaveChildrenWithLayoutBoxesDisabled, // Guard value BooleanFlagCount }; @@ -1790,6 +1793,20 @@ public: { return GetBoolFlag(MayBeApzAware); } + + void SetMayHaveChildrenWithLayoutBoxesDisabled() + { + SetBoolFlag(NodeMayHaveChildrenWithLayoutBoxesDisabled); + } + void UnsetMayHaveChildrenWithLayoutBoxesDisabled() + { + ClearBoolFlag(NodeMayHaveChildrenWithLayoutBoxesDisabled); + } + bool MayHaveChildrenWithLayoutBoxesDisabled() const + { + return GetBoolFlag(NodeMayHaveChildrenWithLayoutBoxesDisabled); + } + protected: void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); } void SetIsInDocument() { SetBoolFlag(IsInDocument); } diff --git a/dom/base/nsMappedAttributes.cpp b/dom/base/nsMappedAttributes.cpp index 825409adc4..949297c489 100644 --- a/dom/base/nsMappedAttributes.cpp +++ b/dom/base/nsMappedAttributes.cpp @@ -61,17 +61,11 @@ nsMappedAttributes::Clone(bool aWillAddAttr) void* nsMappedAttributes::operator new(size_t aSize, uint32_t aAttrCount) CPP_THROW_NEW { - size_t size = aSize + aAttrCount * sizeof(InternalAttr); + NS_ASSERTION(aAttrCount > 0, "zero-attribute nsMappedAttributes requested"); // aSize will include the mAttrs buffer so subtract that. - // We don't want to under-allocate, however, so do not subtract - // if we have zero attributes. The zero attribute case only happens - // for 's mapped attributes - if (aAttrCount != 0) { - size -= sizeof(void*[1]); - } - - void* newAttrs = ::operator new(size); + void* newAttrs = ::operator new(aSize - sizeof(void*[1]) + + aAttrCount * sizeof(InternalAttr)); #ifdef DEBUG static_cast(newAttrs)->mBufferSize = aAttrCount; diff --git a/dom/html/HTMLBodyElement.cpp b/dom/html/HTMLBodyElement.cpp index d030b69d7b..a91dccfb50 100644 --- a/dom/html/HTMLBodyElement.cpp +++ b/dom/html/HTMLBodyElement.cpp @@ -27,8 +27,180 @@ 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 and not set in the + // reflect them as margin in the + if (bodyMarginWidth == -1 || bodyMarginHeight == -1) { + nsCOMPtr 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 & not in + if (eCompatibility_NavQuirks == mode) { + if ((bodyMarginHeight == -1) && (0 > frameMarginHeight)) // nav quirk + frameMarginHeight = 0; + } + } + if ((frameMarginHeight >= 0) && (bodyMarginHeight == -1)) { // set in & not in + 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* @@ -175,6 +347,17 @@ HTMLBodyElement::ParseAttribute(int32_t aNamespaceID, aResult); } +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) @@ -230,6 +413,22 @@ 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 { @@ -238,12 +437,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 }, }; @@ -292,37 +491,6 @@ 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, - const nsAttrValue* aOldValue, bool aNotify) -{ - nsresult rv = nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, - aName, aValue, aOldValue, - 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 while other getters return diff --git a/dom/html/HTMLBodyElement.h b/dom/html/HTMLBodyElement.h index c637731a02..858bc691a9 100644 --- a/dom/html/HTMLBodyElement.h +++ b/dom/html/HTMLBodyElement.h @@ -14,6 +14,28 @@ 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 @@ -102,29 +124,23 @@ 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 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, - const nsAttrValue* aOldValue, - bool aNotify) override; - protected: virtual ~HTMLBodyElement(); virtual JSObject* WrapNode(JSContext *aCx, JS::Handle aGivenProto) override; + RefPtr mContentStyleRule; + private: static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData); diff --git a/dom/html/HTMLTableCellElement.cpp b/dom/html/HTMLTableCellElement.cpp index 2c795d2d49..41e202e8a5 100644 --- a/dom/html/HTMLTableCellElement.cpp +++ b/dom/html/HTMLTableCellElement.cpp @@ -106,7 +106,9 @@ HTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker) nsresult rv = nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker); NS_ENSURE_SUCCESS(rv, rv); - if (nsMappedAttributes* tableInheritedAttributes = GetMappedAttributesInheritedFromTable()) { + if (HTMLTableElement* table = GetTable()) { + nsMappedAttributes* tableInheritedAttributes = + table->GetAttributesMappedForCell(); if (tableInheritedAttributes) { aRuleWalker->Forward(tableInheritedAttributes); } @@ -114,16 +116,6 @@ 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 10af61fc25..59634840e8 100644 --- a/dom/html/HTMLTableCellElement.h +++ b/dom/html/HTMLTableCellElement.h @@ -147,8 +147,6 @@ 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 c33d8de772..a2a6937432 100644 --- a/dom/html/HTMLTableElement.cpp +++ b/dom/html/HTMLTableElement.cpp @@ -321,7 +321,7 @@ TableRowsCollection::ParentDestroyed() HTMLTableElement::HTMLTableElement(already_AddRefed& aNodeInfo) : nsGenericHTMLElement(aNodeInfo), - mTableInheritedAttributes(nullptr) + mTableInheritedAttributes(TABLE_ATTRS_DIRTY) { SetHasWeirdParserInsertionMode(); } @@ -911,15 +911,20 @@ MapInheritedTableAttributesIntoRule(const nsMappedAttributes* aAttributes, nsMappedAttributes* HTMLTableElement::GetAttributesMappedForCell() { - return mTableInheritedAttributes; + if (mTableInheritedAttributes) { + if (mTableInheritedAttributes == TABLE_ATTRS_DIRTY) + BuildInheritedAttributes(); + if (mTableInheritedAttributes != TABLE_ATTRS_DIRTY) + return mTableInheritedAttributes; + } + return nullptr; } void HTMLTableElement::BuildInheritedAttributes() { - NS_ASSERTION(!mTableInheritedAttributes, + NS_ASSERTION(mTableInheritedAttributes == TABLE_ATTRS_DIRTY, "potential leak, plus waste of work"); - MOZ_ASSERT(NS_IsMainThread()); nsIDocument *document = GetComposedDoc(); nsHTMLStyleSheet* sheet = document ? document->GetAttributeStyleSheet() : nullptr; @@ -956,7 +961,10 @@ HTMLTableElement::BuildInheritedAttributes() void HTMLTableElement::ReleaseInheritedAttributes() { - NS_IF_RELEASE(mTableInheritedAttributes); + if (mTableInheritedAttributes && + mTableInheritedAttributes != TABLE_ATTRS_DIRTY) + NS_RELEASE(mTableInheritedAttributes); + mTableInheritedAttributes = TABLE_ATTRS_DIRTY; } nsresult @@ -965,12 +973,9 @@ HTMLTableElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, bool aCompileEventHandlers) { ReleaseInheritedAttributes(); - nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, - aBindingParent, - aCompileEventHandlers); - NS_ENSURE_SUCCESS(rv, rv); - BuildInheritedAttributes(); - return NS_OK; + return nsGenericHTMLElement::BindToTree(aDocument, aParent, + aBindingParent, + aCompileEventHandlers); } void diff --git a/dom/html/HTMLTableElement.h b/dom/html/HTMLTableElement.h index 00faab0ec0..57bf8705e7 100644 --- a/dom/html/HTMLTableElement.h +++ b/dom/html/HTMLTableElement.h @@ -13,6 +13,8 @@ namespace mozilla { namespace dom { +#define TABLE_ATTRS_DIRTY ((nsMappedAttributes*)0x1) + class TableRowsCollection; class HTMLTableElement final : public nsGenericHTMLElement @@ -219,6 +221,8 @@ protected: RefPtr mTBodies; RefPtr 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/reftest-stylo.list b/dom/html/reftests/reftest-stylo.list deleted file mode 100644 index 570c073587..0000000000 --- a/dom/html/reftests/reftest-stylo.list +++ /dev/null @@ -1,73 +0,0 @@ -# DO NOT EDIT! This is a auto-generated temporary list for Stylo testing -# autofocus attribute (we can't test with mochitests) -# many stylo intermittents in files below -# include autofocus/reftest-stylo.list -# include toblob-todataurl/reftest-stylo.list - -skip-if(B2G) == 41464-1a.html 41464-1a.html -skip-if(B2G) == 41464-1b.html 41464-1b.html -== 52019-1.html 52019-1.html -== 82711-1.html 82711-1.html -== 82711-2.html 82711-2.html -== 82711-1-ref.html 82711-1-ref.html -random == 468263-1a.html 468263-1a.html -random == 468263-1b.html 468263-1b.html -random == 468263-1c.html 468263-1c.html -random == 468263-1d.html 468263-1d.html -random == 468263-2.html 468263-2.html -random == 468263-2.html 468263-2.html -== 484200-1.html 484200-1.html -== 485377.html 485377.html -== 557840.html 557840.html -== 560059-video-dimensions.html 560059-video-dimensions.html -== 573322-quirks.html 573322-quirks.html -== 573322-no-quirks.html 573322-no-quirks.html -# == 596455-1a.html 596455-1a.html -== 596455-1b.html 596455-1b.html -== 596455-2a.html 596455-2a.html -== 596455-2b.html 596455-2b.html -== 610935.html 610935.html -== 649134-1.html 649134-1.html -skip-if(Android||B2G) == 649134-2.html 649134-2.html - -== bug448564-1_malformed.html bug448564-1_malformed.html -== bug448564-1_malformed.html bug448564-1_malformed.html - -== bug448564-4a.html bug448564-4a.html -== bug502168-1_malformed.html bug502168-1_malformed.html - -random == responsive-image-load-shortcircuit.html responsive-image-load-shortcircuit.html - -# Test that image documents taken into account CSS properties like -# image-orientation when determining the size of the image. -# (Fuzzy necessary due to pixel-wise comparison of different JPEGs. -# The vast majority of the fuzziness comes from Linux and WinXP.) -skip == bug917595-iframe-1.html bug917595-iframe-1.html -skip == bug917595-exif-rotated.jpg bug917595-exif-rotated.jpg -# bug 1060869 -# Bug 1150490 disabling on Mulet as on B2G - -# Test support for SVG-as-image in elements. -== bug1106522-1.html bug1106522-1.html -== bug1106522-2.html bug1106522-2.html - -== href-attr-change-restyles.html href-attr-change-restyles.html -== figure.html figure.html -== pre-1.html pre-1.html -== table-border-1.html table-border-1.html -== table-border-2.html table-border-2.html -== table-border-2.html table-border-2.html - -# Test imageset is using permissions.default.image -pref(permissions.default.image,1) HTTP == bug1196784-with-srcset.html bug1196784-with-srcset.html -pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784-with-srcset.html - -# 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/test/body-margin-test/child.html b/dom/html/test/body-margin-test/child.html new file mode 100644 index 0000000000..d740fb058a --- /dev/null +++ b/dom/html/test/body-margin-test/child.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dom/html/test/body-margin-test/fruit.jpg b/dom/html/test/body-margin-test/fruit.jpg new file mode 100644 index 0000000000..d43db35e18 Binary files /dev/null and b/dom/html/test/body-margin-test/fruit.jpg differ diff --git a/dom/html/test/body-margin-test/test-body.html b/dom/html/test/body-margin-test/test-body.html new file mode 100644 index 0000000000..c63ea72640 --- /dev/null +++ b/dom/html/test/body-margin-test/test-body.html @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dom/html/test/body-margin-test/test-frame.html b/dom/html/test/body-margin-test/test-frame.html new file mode 100644 index 0000000000..0c246188a4 --- /dev/null +++ b/dom/html/test/body-margin-test/test-frame.html @@ -0,0 +1,11 @@ + + + + iframe now showing margin/padding in pale moon + + + + +