diff options
Diffstat (limited to 'dom/html')
193 files changed, 1819 insertions, 2743 deletions
diff --git a/dom/html/HTMLAllCollection.cpp b/dom/html/HTMLAllCollection.cpp index 6305cce31..9335fbebd 100644 --- a/dom/html/HTMLAllCollection.cpp +++ b/dom/html/HTMLAllCollection.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLAllCollection.h b/dom/html/HTMLAllCollection.h index aed72eaaa..5c454286c 100644 --- a/dom/html/HTMLAllCollection.h +++ b/dom/html/HTMLAllCollection.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLAnchorElement.cpp b/dom/html/HTMLAnchorElement.cpp index a6cfacc53..2dc20cff0 100644 --- a/dom/html/HTMLAnchorElement.cpp +++ b/dom/html/HTMLAnchorElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -14,6 +13,7 @@ #include "nsContentUtils.h" #include "nsGkAtoms.h" #include "nsHTMLDNSPrefetch.h" +#include "nsAttrValueOrString.h" #include "nsIDocument.h" #include "nsIPresShell.h" #include "nsPresContext.h" @@ -252,9 +252,9 @@ HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse, } nsresult -HTMLAnchorElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLAnchorElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { - return PreHandleEventForAnchors(aVisitor); + return GetEventTargetParentForAnchors(aVisitor); } nsresult @@ -372,84 +372,37 @@ HTMLAnchorElement::GetHrefURI() const } nsresult -HTMLAnchorElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) +HTMLAnchorElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) { - bool reset = false; - if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) { - // If we do not have a cached URI, we have some value here so we must reset - // our link state after calling the parent. - if (!Link::HasCachedURI()) { - reset = true; - } - // However, if we have a cached URI, we'll want to see if the value changed. - else { - nsAutoString val; - GetHref(val); - if (!val.Equals(aValue)) { - reset = true; - } - } - if (reset) { + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::href) { CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED, HTML_ANCHOR_DNS_PREFETCH_REQUESTED); } } - nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, - aValue, aNotify); - - // The ordering of the parent class's SetAttr call and Link::ResetLinkState - // is important here! The attribute is not set until SetAttr returns, and - // we will need the updated attribute value because notifying the document - // that content states have changed will call IntrinsicState, which will try - // to get updated information about the visitedness from Link. - if (reset) { - Link::ResetLinkState(!!aNotify, true); - if (IsInComposedDoc()) { - TryDNSPrefetch(); - } - } - - return rv; + return nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, aValue, + aNotify); } nsresult -HTMLAnchorElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) +HTMLAnchorElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { - bool href = - (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID); - - if (href) { - CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED, - HTML_ANCHOR_DNS_PREFETCH_REQUESTED); - } - - nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, - aNotify); - - // The ordering of the parent class's UnsetAttr call and Link::ResetLinkState - // is important here! The attribute is not unset until UnsetAttr returns, and - // we will need the updated attribute value because notifying the document - // that content states have changed will call IntrinsicState, which will try - // to get updated information about the visitedness from Link. - if (href) { - Link::ResetLinkState(!!aNotify, false); + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::href) { + Link::ResetLinkState(aNotify, !!aValue); + if (aValue && IsInComposedDoc()) { + TryDNSPrefetch(); + } + } } - return rv; -} - -bool -HTMLAnchorElement::ParseAttribute(int32_t aNamespaceID, - nsIAtom* aAttribute, - const nsAString& aValue, - nsAttrValue& aResult) -{ - return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, - aResult); + return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, + aValue, aOldValue, aNotify); } EventStates diff --git a/dom/html/HTMLAnchorElement.h b/dom/html/HTMLAnchorElement.h index 2cb04ad93..c80c823c7 100644 --- a/dom/html/HTMLAnchorElement.h +++ b/dom/html/HTMLAnchorElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -58,27 +57,21 @@ public: bool aNullParent = true) override; virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override; - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; virtual bool IsLink(nsIURI** aURI) const override; virtual void GetLinkTarget(nsAString& aTarget) override; virtual already_AddRefed<nsIURI> GetHrefURI() const override; - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) override; - virtual bool ParseAttribute(int32_t aNamespaceID, - nsIAtom* aAttribute, - const nsAString& aValue, - nsAttrValue& aResult) override; + virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) override; + virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; diff --git a/dom/html/HTMLAreaElement.cpp b/dom/html/HTMLAreaElement.cpp index 098081b8b..2ffc00848 100644 --- a/dom/html/HTMLAreaElement.cpp +++ b/dom/html/HTMLAreaElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -81,9 +80,9 @@ HTMLAreaElement::SetTarget(const nsAString& aValue) } nsresult -HTMLAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLAreaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { - return PreHandleEventForAnchors(aVisitor); + return GetEventTargetParentForAnchors(aVisitor); } nsresult @@ -153,42 +152,22 @@ HTMLAreaElement::UnbindFromTree(bool aDeep, bool aNullParent) } nsresult -HTMLAreaElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) -{ - nsresult rv = - nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, aNotify); - - // The ordering of the parent class's SetAttr call and Link::ResetLinkState - // is important here! The attribute is not set until SetAttr returns, and - // we will need the updated attribute value because notifying the document - // that content states have changed will call IntrinsicState, which will try - // to get updated information about the visitedness from Link. - if (aName == nsGkAtoms::href && aNameSpaceID == kNameSpaceID_None) { - Link::ResetLinkState(!!aNotify, true); +HTMLAreaElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) +{ + if (aNamespaceID == kNameSpaceID_None) { + // This must happen after the attribute is set. We will need the updated + // attribute value because notifying the document that content states have + // changed will call IntrinsicState, which will try to get updated + // information about the visitedness from Link. + if (aName == nsGkAtoms::href) { + Link::ResetLinkState(aNotify, !!aValue); + } } - return rv; -} - -nsresult -HTMLAreaElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) -{ - nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, - aNotify); - - // The ordering of the parent class's UnsetAttr call and Link::ResetLinkState - // is important here! The attribute is not unset until UnsetAttr returns, and - // we will need the updated attribute value because notifying the document - // that content states have changed will call IntrinsicState, which will try - // to get updated information about the visitedness from Link. - if (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) { - Link::ResetLinkState(!!aNotify, false); - } - - return rv; + return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, + aOldValue, aNotify); } #define IMPL_URI_PART(_part) \ diff --git a/dom/html/HTMLAreaElement.h b/dom/html/HTMLAreaElement.h index 650c0fd8f..919ba9d60 100644 --- a/dom/html/HTMLAreaElement.h +++ b/dom/html/HTMLAreaElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -44,7 +43,8 @@ public: // nsIDOMHTMLAreaElement NS_DECL_NSIDOMHTMLAREAELEMENT - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; virtual bool IsLink(nsIURI** aURI) const override; virtual void GetLinkTarget(nsAString& aTarget) override; @@ -55,16 +55,6 @@ public: bool aCompileEventHandlers) override; virtual void UnbindFromTree(bool aDeep = true, bool aNullParent = true) override; - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) override; virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override; @@ -185,6 +175,11 @@ protected: virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; + virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; + RefPtr<nsDOMTokenList > mRelList; }; diff --git a/dom/html/HTMLAudioElement.cpp b/dom/html/HTMLAudioElement.cpp index 0722c7b15..6ec048836 100644 --- a/dom/html/HTMLAudioElement.cpp +++ b/dom/html/HTMLAudioElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLAudioElement.h b/dom/html/HTMLAudioElement.h index 138131cd9..4c98c1480 100644 --- a/dom/html/HTMLAudioElement.h +++ b/dom/html/HTMLAudioElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLBRElement.cpp b/dom/html/HTMLBRElement.cpp index db51a4d7e..83bbdff8f 100644 --- a/dom/html/HTMLBRElement.cpp +++ b/dom/html/HTMLBRElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLBRElement.h b/dom/html/HTMLBRElement.h index cf7aaaedc..63c22767a 100644 --- a/dom/html/HTMLBRElement.h +++ b/dom/html/HTMLBRElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLBodyElement.cpp b/dom/html/HTMLBodyElement.cpp index ee1bced02..d030b69d7 100644 --- a/dom/html/HTMLBodyElement.cpp +++ b/dom/html/HTMLBodyElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -28,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* @@ -349,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) { @@ -414,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 { @@ -438,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 }, }; @@ -492,6 +292,37 @@ 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<EventHandlerNonNull> while other getters return diff --git a/dom/html/HTMLBodyElement.h b/dom/html/HTMLBodyElement.h index 436dc4cba..c637731a0 100644 --- a/dom/html/HTMLBodyElement.h +++ b/dom/html/HTMLBodyElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -15,28 +14,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 +102,29 @@ 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, + const nsAttrValue* aOldValue, + 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/HTMLButtonElement.cpp b/dom/html/HTMLButtonElement.cpp index 609eb7a66..e493d1891 100644 --- a/dom/html/HTMLButtonElement.cpp +++ b/dom/html/HTMLButtonElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -207,7 +206,7 @@ HTMLButtonElement::IsDisabledForEvents(WidgetEvent* aEvent) } nsresult -HTMLButtonElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLButtonElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = false; if (IsDisabledForEvents(aVisitor.mEvent)) { @@ -235,7 +234,7 @@ HTMLButtonElement::PreHandleEvent(EventChainPreVisitor& aVisitor) } } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } nsresult @@ -423,7 +422,7 @@ HTMLButtonElement::DoneCreatingElement() nsresult HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) { if (aNotify && aName == nsGkAtoms::disabled && @@ -437,7 +436,8 @@ HTMLButtonElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::type) { @@ -448,12 +448,12 @@ HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, if (aName == nsGkAtoms::type || aName == nsGkAtoms::disabled) { UpdateBarredFromConstraintValidation(); - UpdateState(aNotify); } } return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, - aValue, aNotify); + aValue, aOldValue, + aNotify); } NS_IMETHODIMP diff --git a/dom/html/HTMLButtonElement.h b/dom/html/HTMLButtonElement.h index d15d11b6d..139596ae3 100644 --- a/dom/html/HTMLButtonElement.h +++ b/dom/html/HTMLButtonElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -57,7 +56,8 @@ public: virtual void FieldSetDisabledChanged(bool aNotify) override; // nsIDOMEventTarget - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; @@ -80,13 +80,15 @@ public: * Called when an attribute is about to be changed */ virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) override; /** * Called when an attribute has just been changed */ - nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; virtual bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute, const nsAString& aValue, diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index 4b5deab18..11d909373 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -446,38 +445,37 @@ NS_IMPL_UINT_ATTR_DEFAULT_VALUE(HTMLCanvasElement, Height, height, DEFAULT_CANVA NS_IMPL_BOOL_ATTR(HTMLCanvasElement, MozOpaque, moz_opaque) nsresult -HTMLCanvasElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) -{ - nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, - aNotify); - if (NS_SUCCEEDED(rv) && mCurrentContext && - aNameSpaceID == kNameSpaceID_None && - (aName == nsGkAtoms::width || aName == nsGkAtoms::height || aName == nsGkAtoms::moz_opaque)) - { - ErrorResult dummy; - rv = UpdateContext(nullptr, JS::NullHandleValue, dummy); - NS_ENSURE_SUCCESS(rv, rv); - } +HTMLCanvasElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) +{ + AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); - return rv; + return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, + aOldValue, aNotify); } nsresult -HTMLCanvasElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName, - bool aNotify) +HTMLCanvasElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) { - nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aName, aNotify); - if (NS_SUCCEEDED(rv) && mCurrentContext && - aNameSpaceID == kNameSpaceID_None && - (aName == nsGkAtoms::width || aName == nsGkAtoms::height || aName == nsGkAtoms::moz_opaque)) - { + AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); + + return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName, + aValue, aNotify); +} + +void +HTMLCanvasElement::AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + bool aNotify) +{ + if (mCurrentContext && aNamespaceID == kNameSpaceID_None && + (aName == nsGkAtoms::width || aName == nsGkAtoms::height || + aName == nsGkAtoms::moz_opaque)) { ErrorResult dummy; - rv = UpdateContext(nullptr, JS::NullHandleValue, dummy); - NS_ENSURE_SUCCESS(rv, rv); + UpdateContext(nullptr, JS::NullHandleValue, dummy); } - return rv; } void @@ -574,7 +572,7 @@ HTMLCanvasElement::CopyInnerTo(Element* aDest) return rv; } -nsresult HTMLCanvasElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +nsresult HTMLCanvasElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { if (aVisitor.mEvent->mClass == eMouseEventClass) { WidgetMouseEventBase* evt = (WidgetMouseEventBase*)aVisitor.mEvent; @@ -592,7 +590,7 @@ nsresult HTMLCanvasElement::PreHandleEvent(EventChainPreVisitor& aVisitor) aVisitor.mCanHandle = true; } } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } nsChangeHint diff --git a/dom/html/HTMLCanvasElement.h b/dom/html/HTMLCanvasElement.h index e77db6ff1..b84f2eac9 100644 --- a/dom/html/HTMLCanvasElement.h +++ b/dom/html/HTMLCanvasElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -295,24 +294,11 @@ public: nsAttrValue& aResult) override; nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, int32_t aModType) const override; - // SetAttr override. C++ is stupid, so have to override both - // overloaded methods. - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName, - bool aNotify) override; - virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; nsresult CopyInnerTo(mozilla::dom::Element* aDest); - virtual nsresult PreHandleEvent(mozilla::EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + mozilla::EventChainPreVisitor& aVisitor) override; /* * Helpers called by various users of Canvas @@ -372,6 +358,14 @@ protected: nsISupports** aResult); void CallPrintCallback(); + virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; + virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) override; + AsyncCanvasRenderer* GetAsyncCanvasRenderer(); bool mResetLayer; @@ -405,6 +399,18 @@ public: CanvasContextType GetCurrentContextType() { return mCurrentContextType; } + +private: + /** + * This function is called by AfterSetAttr and OnAttrSetButNotChanged. + * This function will be called by AfterSetAttr whether the attribute is being + * set or unset. + * + * @param aNamespaceID the namespace of the attr being set + * @param aName the localname of the attribute being set + * @param aNotify Whether we plan to notify document observers. + */ + void AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, bool aNotify); }; class HTMLCanvasPrintState final : public nsWrapperCache diff --git a/dom/html/HTMLContentElement.cpp b/dom/html/HTMLContentElement.cpp deleted file mode 100644 index 01c0158a0..000000000 --- a/dom/html/HTMLContentElement.cpp +++ /dev/null @@ -1,393 +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 "mozilla/dom/HTMLContentElement.h" -#include "mozilla/dom/HTMLContentElementBinding.h" -#include "mozilla/dom/HTMLUnknownElement.h" -#include "mozilla/dom/NodeListBinding.h" -#include "mozilla/dom/ShadowRoot.h" -#include "mozilla/css/StyleRule.h" -#include "nsGkAtoms.h" -#include "nsStyleConsts.h" -#include "nsIAtom.h" -#include "nsCSSRuleProcessor.h" -#include "nsRuleData.h" -#include "nsRuleProcessorData.h" -#include "nsRuleWalker.h" -#include "nsCSSParser.h" -#include "nsDocument.h" - -// Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Content) to add check for web components -// being enabled. -nsGenericHTMLElement* -NS_NewHTMLContentElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, - mozilla::dom::FromParser aFromParser) -{ - // When this check is removed, remove the nsDocument.h and - // HTMLUnknownElement.h includes. Also remove nsINode::IsHTMLContentElement. - // - // We have to jump through some hoops to be able to produce both NodeInfo* and - // already_AddRefed<NodeInfo>& for our callees. - RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo); - if (!nsDocument::IsWebComponentsEnabled(nodeInfo)) { - already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget()); - return new mozilla::dom::HTMLUnknownElement(nodeInfoArg); - } - - already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget()); - return new mozilla::dom::HTMLContentElement(nodeInfoArg); -} - -using namespace mozilla::dom; - -HTMLContentElement::HTMLContentElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) - : nsGenericHTMLElement(aNodeInfo), mValidSelector(true), mIsInsertionPoint(false) -{ -} - -HTMLContentElement::~HTMLContentElement() -{ -} - -NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLContentElement, - nsGenericHTMLElement, - mMatchedNodes) - -NS_IMPL_ADDREF_INHERITED(HTMLContentElement, Element) -NS_IMPL_RELEASE_INHERITED(HTMLContentElement, Element) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLContentElement) -NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement) - -NS_IMPL_ELEMENT_CLONE(HTMLContentElement) - -JSObject* -HTMLContentElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) -{ - return HTMLContentElementBinding::Wrap(aCx, this, aGivenProto); -} - -nsresult -HTMLContentElement::BindToTree(nsIDocument* aDocument, - nsIContent* aParent, - nsIContent* aBindingParent, - bool aCompileEventHandlers) -{ - RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow(); - - nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, - aBindingParent, - aCompileEventHandlers); - NS_ENSURE_SUCCESS(rv, rv); - - ShadowRoot* containingShadow = GetContainingShadow(); - if (containingShadow && !oldContainingShadow) { - nsINode* parentNode = nsINode::GetParentNode(); - while (parentNode && parentNode != containingShadow) { - if (parentNode->IsHTMLContentElement()) { - // Content element in fallback content is not an insertion point. - return NS_OK; - } - parentNode = parentNode->GetParentNode(); - } - - // If the content element is being inserted into a ShadowRoot, - // add this element to the list of insertion points. - mIsInsertionPoint = true; - containingShadow->AddInsertionPoint(this); - containingShadow->SetInsertionPointChanged(); - } - - return NS_OK; -} - -void -HTMLContentElement::UnbindFromTree(bool aDeep, bool aNullParent) -{ - RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow(); - - nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); - - if (oldContainingShadow && !GetContainingShadow() && mIsInsertionPoint) { - oldContainingShadow->RemoveInsertionPoint(this); - - // Remove all the matched nodes now that the - // insertion point is no longer an insertion point. - ClearMatchedNodes(); - oldContainingShadow->SetInsertionPointChanged(); - - mIsInsertionPoint = false; - } -} - -void -HTMLContentElement::AppendMatchedNode(nsIContent* aContent) -{ - mMatchedNodes.AppendElement(aContent); - nsTArray<nsIContent*>& destInsertionPoint = aContent->DestInsertionPoints(); - destInsertionPoint.AppendElement(this); - - if (mMatchedNodes.Length() == 1) { - // Fallback content gets dropped so we need to updated fallback - // content distribution. - UpdateFallbackDistribution(); - } -} - -void -HTMLContentElement::UpdateFallbackDistribution() -{ - for (nsIContent* child = nsINode::GetFirstChild(); - child; - child = child->GetNextSibling()) { - nsTArray<nsIContent*>& destInsertionPoint = child->DestInsertionPoints(); - destInsertionPoint.Clear(); - if (mMatchedNodes.IsEmpty()) { - destInsertionPoint.AppendElement(this); - } - } -} - -void -HTMLContentElement::RemoveMatchedNode(nsIContent* aContent) -{ - mMatchedNodes.RemoveElement(aContent); - ShadowRoot::RemoveDestInsertionPoint(this, aContent->DestInsertionPoints()); - - if (mMatchedNodes.IsEmpty()) { - // Fallback content is activated so we need to update fallback - // content distribution. - UpdateFallbackDistribution(); - } -} - -void -HTMLContentElement::InsertMatchedNode(uint32_t aIndex, nsIContent* aContent) -{ - mMatchedNodes.InsertElementAt(aIndex, aContent); - nsTArray<nsIContent*>& destInsertionPoint = aContent->DestInsertionPoints(); - destInsertionPoint.AppendElement(this); - - if (mMatchedNodes.Length() == 1) { - // Fallback content gets dropped so we need to updated fallback - // content distribution. - UpdateFallbackDistribution(); - } -} - -void -HTMLContentElement::ClearMatchedNodes() -{ - for (uint32_t i = 0; i < mMatchedNodes.Length(); i++) { - ShadowRoot::RemoveDestInsertionPoint(this, mMatchedNodes[i]->DestInsertionPoints()); - } - - mMatchedNodes.Clear(); - - UpdateFallbackDistribution(); -} - -static bool -IsValidContentSelectors(nsCSSSelector* aSelector) -{ - nsCSSSelector* currentSelector = aSelector; - while (currentSelector) { - // Blacklist invalid selector fragments. - if (currentSelector->IsPseudoElement() || - currentSelector->mPseudoClassList || - currentSelector->mNegations || - currentSelector->mOperator) { - return false; - } - - currentSelector = currentSelector->mNext; - } - - return true; -} - -nsresult -HTMLContentElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) -{ - nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, - aValue, aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::select) { - // Select attribute was updated, the insertion point may match different - // elements. - nsIDocument* doc = OwnerDoc(); - nsCSSParser parser(doc->CSSLoader()); - - mValidSelector = true; - mSelectorList = nullptr; - - nsresult rv = parser.ParseSelectorString(aValue, - doc->GetDocumentURI(), - // Bug 11240 - 0, // XXX get the line number! - getter_Transfers(mSelectorList)); - - // We don't want to return an exception if parsing failed because - // the spec does not define it as an exception case. - if (NS_SUCCEEDED(rv)) { - // Ensure that all the selectors are valid - nsCSSSelectorList* selectors = mSelectorList; - while (selectors) { - if (!IsValidContentSelectors(selectors->mSelectors)) { - // If we have an invalid selector, we can not match anything. - mValidSelector = false; - mSelectorList = nullptr; - break; - } - selectors = selectors->mNext; - } - } - - ShadowRoot* containingShadow = GetContainingShadow(); - if (containingShadow) { - containingShadow->DistributeAllNodes(); - } - } - - return NS_OK; -} - -nsresult -HTMLContentElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) -{ - nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, - aAttribute, aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::select) { - // The select attribute was removed. This insertion point becomes - // a universal selector. - mValidSelector = true; - mSelectorList = nullptr; - - ShadowRoot* containingShadow = GetContainingShadow(); - if (containingShadow) { - containingShadow->DistributeAllNodes(); - } - } - - return NS_OK; -} - -bool -HTMLContentElement::Match(nsIContent* aContent) -{ - if (!mValidSelector) { - return false; - } - - if (mSelectorList) { - nsIDocument* doc = OwnerDoc(); - ShadowRoot* containingShadow = GetContainingShadow(); - nsIContent* host = containingShadow->GetHost(); - - TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited, - doc, TreeMatchContext::eNeverMatchVisited); - doc->FlushPendingLinkUpdates(); - matchingContext.SetHasSpecifiedScope(); - matchingContext.AddScopeElement(host->AsElement()); - - if (!aContent->IsElement()) { - return false; - } - - return nsCSSRuleProcessor::SelectorListMatches(aContent->AsElement(), - matchingContext, - mSelectorList); - } - - return true; -} - -already_AddRefed<DistributedContentList> -HTMLContentElement::GetDistributedNodes() -{ - RefPtr<DistributedContentList> list = new DistributedContentList(this); - return list.forget(); -} - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DistributedContentList, mParent, - mDistributedNodes) - -NS_INTERFACE_TABLE_HEAD(DistributedContentList) - NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY - NS_INTERFACE_TABLE(DistributedContentList, nsINodeList, nsIDOMNodeList) - NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(DistributedContentList) -NS_INTERFACE_MAP_END - -NS_IMPL_CYCLE_COLLECTING_ADDREF(DistributedContentList) -NS_IMPL_CYCLE_COLLECTING_RELEASE(DistributedContentList) - -DistributedContentList::DistributedContentList(HTMLContentElement* aHostElement) - : mParent(aHostElement) -{ - MOZ_COUNT_CTOR(DistributedContentList); - - if (aHostElement->IsInsertionPoint()) { - if (aHostElement->MatchedNodes().IsEmpty()) { - // Fallback content. - nsINode* contentNode = aHostElement; - for (nsIContent* content = contentNode->GetFirstChild(); - content; - content = content->GetNextSibling()) { - mDistributedNodes.AppendElement(content); - } - } else { - mDistributedNodes.AppendElements(aHostElement->MatchedNodes()); - } - } -} - -DistributedContentList::~DistributedContentList() -{ - MOZ_COUNT_DTOR(DistributedContentList); -} - -nsIContent* -DistributedContentList::Item(uint32_t aIndex) -{ - return mDistributedNodes.SafeElementAt(aIndex); -} - -NS_IMETHODIMP -DistributedContentList::Item(uint32_t aIndex, nsIDOMNode** aReturn) -{ - nsIContent* item = Item(aIndex); - if (!item) { - return NS_ERROR_FAILURE; - } - - return CallQueryInterface(item, aReturn); -} - -NS_IMETHODIMP -DistributedContentList::GetLength(uint32_t* aLength) -{ - *aLength = mDistributedNodes.Length(); - return NS_OK; -} - -int32_t -DistributedContentList::IndexOf(nsIContent* aContent) -{ - return mDistributedNodes.IndexOf(aContent); -} - -JSObject* -DistributedContentList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) -{ - return NodeListBinding::Wrap(aCx, this, aGivenProto); -} - diff --git a/dom/html/HTMLContentElement.h b/dom/html/HTMLContentElement.h deleted file mode 100644 index f019e56cd..000000000 --- a/dom/html/HTMLContentElement.h +++ /dev/null @@ -1,135 +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/. */ - -#ifndef mozilla_dom_HTMLContentElement_h__ -#define mozilla_dom_HTMLContentElement_h__ - -#include "nsAutoPtr.h" -#include "nsINodeList.h" -#include "nsGenericHTMLElement.h" - -struct nsCSSSelectorList; - -namespace mozilla { -namespace dom { - -class DistributedContentList; - -class HTMLContentElement final : public nsGenericHTMLElement -{ -public: - explicit HTMLContentElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo); - - // nsISupports - NS_DECL_ISUPPORTS_INHERITED - - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLContentElement, - nsGenericHTMLElement) - - static HTMLContentElement* FromContent(nsIContent* aContent) - { - if (aContent->IsHTMLContentElement()) { - return static_cast<HTMLContentElement*>(aContent); - } - - return nullptr; - } - - virtual bool IsHTMLContentElement() const override { return true; } - - virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; - - virtual nsIDOMNode* AsDOMNode() override { return this; } - - virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, - nsIContent* aBindingParent, - bool aCompileEventHandlers) override; - - virtual void UnbindFromTree(bool aDeep = true, - bool aNullParent = true) override; - - /** - * Returns whether if the selector of this insertion point - * matches the provided content. - */ - bool Match(nsIContent* aContent); - bool IsInsertionPoint() const { return mIsInsertionPoint; } - nsCOMArray<nsIContent>& MatchedNodes() { return mMatchedNodes; } - void AppendMatchedNode(nsIContent* aContent); - void RemoveMatchedNode(nsIContent* aContent); - void InsertMatchedNode(uint32_t aIndex, nsIContent* aContent); - void ClearMatchedNodes(); - - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) override; - - // WebIDL methods. - already_AddRefed<DistributedContentList> GetDistributedNodes(); - void GetSelect(nsAString& aSelect) - { - Element::GetAttr(kNameSpaceID_None, nsGkAtoms::select, aSelect); - } - void SetSelect(const nsAString& aSelect) - { - Element::SetAttr(kNameSpaceID_None, nsGkAtoms::select, aSelect, true); - } - -protected: - virtual ~HTMLContentElement(); - - virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override; - - /** - * Updates the destination insertion points of the fallback - * content of this insertion point. If there are nodes matched - * to this insertion point, then destination insertion points - * of fallback are cleared, otherwise, this insertion point - * is a destination insertion point. - */ - void UpdateFallbackDistribution(); - - /** - * An array of nodes from the ShadowRoot host that match the - * content insertion selector. - */ - nsCOMArray<nsIContent> mMatchedNodes; - - nsAutoPtr<nsCSSSelectorList> mSelectorList; - bool mValidSelector; - bool mIsInsertionPoint; -}; - -class DistributedContentList : public nsINodeList -{ -public: - explicit DistributedContentList(HTMLContentElement* aHostElement); - - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DistributedContentList) - - // nsIDOMNodeList - NS_DECL_NSIDOMNODELIST - - // nsINodeList - virtual nsIContent* Item(uint32_t aIndex) override; - virtual int32_t IndexOf(nsIContent* aContent) override; - virtual nsINode* GetParentObject() override { return mParent; } - virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; -protected: - virtual ~DistributedContentList(); - RefPtr<HTMLContentElement> mParent; - nsCOMArray<nsIContent> mDistributedNodes; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_HTMLContentElement_h__ - diff --git a/dom/html/HTMLDataElement.cpp b/dom/html/HTMLDataElement.cpp index e9d53e573..baf9ef989 100644 --- a/dom/html/HTMLDataElement.cpp +++ b/dom/html/HTMLDataElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLDataElement.h b/dom/html/HTMLDataElement.h index 4fd26a017..7ca2197f6 100644 --- a/dom/html/HTMLDataElement.h +++ b/dom/html/HTMLDataElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLDataListElement.cpp b/dom/html/HTMLDataListElement.cpp index 5aa772645..41eec0cc4 100644 --- a/dom/html/HTMLDataListElement.cpp +++ b/dom/html/HTMLDataListElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLDataListElement.h b/dom/html/HTMLDataListElement.h index ba2a2e0b4..eb026dab7 100644 --- a/dom/html/HTMLDataListElement.h +++ b/dom/html/HTMLDataListElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLDetailsElement.cpp b/dom/html/HTMLDetailsElement.cpp index ed20b50ca..9d4dd89c2 100644 --- a/dom/html/HTMLDetailsElement.cpp +++ b/dom/html/HTMLDetailsElement.cpp @@ -6,39 +6,11 @@ #include "mozilla/dom/HTMLDetailsElement.h" #include "mozilla/dom/HTMLDetailsElementBinding.h" -#include "mozilla/dom/HTMLUnknownElement.h" -#include "mozilla/Preferences.h" - -// Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Details) to add pref check. -nsGenericHTMLElement* -NS_NewHTMLDetailsElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, - mozilla::dom::FromParser aFromParser) -{ - if (!mozilla::dom::HTMLDetailsElement::IsDetailsEnabled()) { - return new mozilla::dom::HTMLUnknownElement(aNodeInfo); - } - - return new mozilla::dom::HTMLDetailsElement(aNodeInfo); -} +NS_IMPL_NS_NEW_HTML_ELEMENT(Details) namespace mozilla { namespace dom { -/* static */ bool -HTMLDetailsElement::IsDetailsEnabled() -{ - static bool isDetailsEnabled = false; - static bool added = false; - - if (!added) { - Preferences::AddBoolVarCache(&isDetailsEnabled, - "dom.details_element.enabled"); - added = true; - } - - return isDetailsEnabled; -} - HTMLDetailsElement::~HTMLDetailsElement() { } @@ -73,7 +45,7 @@ HTMLDetailsElement::GetAttributeChangeHint(const nsIAtom* aAttribute, nsresult HTMLDetailsElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, bool aNotify) + const nsAttrValueOrString* aValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::open) { bool setOpen = aValue != nullptr; diff --git a/dom/html/HTMLDetailsElement.h b/dom/html/HTMLDetailsElement.h index 5a3af27b4..4575ed888 100644 --- a/dom/html/HTMLDetailsElement.h +++ b/dom/html/HTMLDetailsElement.h @@ -23,8 +23,6 @@ class HTMLDetailsElement final : public nsGenericHTMLElement public: using NodeInfo = mozilla::dom::NodeInfo; - static bool IsDetailsEnabled(); - explicit HTMLDetailsElement(already_AddRefed<NodeInfo>& aNodeInfo) : nsGenericHTMLElement(aNodeInfo) { @@ -40,7 +38,8 @@ public: int32_t aModType) const override; nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, bool aNotify) override; + const nsAttrValueOrString* aValue, + bool aNotify) override; // HTMLDetailsElement WebIDL bool Open() const { return GetBoolAttr(nsGkAtoms::open); } diff --git a/dom/html/HTMLDialogElement.cpp b/dom/html/HTMLDialogElement.cpp index 48666628e..a178e5afe 100644 --- a/dom/html/HTMLDialogElement.cpp +++ b/dom/html/HTMLDialogElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLDialogElement.h b/dom/html/HTMLDialogElement.h index efa319f3c..0520ef56b 100644 --- a/dom/html/HTMLDialogElement.h +++ b/dom/html/HTMLDialogElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLDivElement.cpp b/dom/html/HTMLDivElement.cpp index d5b587241..9a019d77c 100644 --- a/dom/html/HTMLDivElement.cpp +++ b/dom/html/HTMLDivElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLDivElement.h b/dom/html/HTMLDivElement.h index 9cd0f84b9..6a570559a 100644 --- a/dom/html/HTMLDivElement.h +++ b/dom/html/HTMLDivElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLElement.cpp b/dom/html/HTMLElement.cpp index b2f23b931..cca7f068b 100644 --- a/dom/html/HTMLElement.cpp +++ b/dom/html/HTMLElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -52,3 +51,12 @@ NS_NewHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, { return new mozilla::dom::HTMLElement(aNodeInfo); } + +// Distinct from the above in order to have function pointer that compared unequal +// to a function pointer to the above. +nsGenericHTMLElement* +NS_NewCustomElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, + mozilla::dom::FromParser aFromParser) +{ + return new mozilla::dom::HTMLElement(aNodeInfo); +} diff --git a/dom/html/HTMLFieldSetElement.cpp b/dom/html/HTMLFieldSetElement.cpp index 788d88791..9052d399e 100644 --- a/dom/html/HTMLFieldSetElement.cpp +++ b/dom/html/HTMLFieldSetElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -70,7 +69,7 @@ HTMLFieldSetElement::IsDisabledForEvents(WidgetEvent* aEvent) // nsIContent nsresult -HTMLFieldSetElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLFieldSetElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { // Do not process any DOM events if the element is disabled. aVisitor.mCanHandle = false; @@ -78,12 +77,13 @@ HTMLFieldSetElement::PreHandleEvent(EventChainPreVisitor& aVisitor) return NS_OK; } - return nsGenericHTMLFormElement::PreHandleEvent(aVisitor); + return nsGenericHTMLFormElement::GetEventTargetParent(aVisitor); } nsresult HTMLFieldSetElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled && nsINode::GetFirstChild()) { @@ -100,7 +100,7 @@ HTMLFieldSetElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, - aValue, aNotify); + aValue, aOldValue, aNotify); } // nsIDOMHTMLFieldSetElement diff --git a/dom/html/HTMLFieldSetElement.h b/dom/html/HTMLFieldSetElement.h index 4a4ab71e4..e56a279c3 100644 --- a/dom/html/HTMLFieldSetElement.h +++ b/dom/html/HTMLFieldSetElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -40,9 +39,12 @@ public: NS_DECL_NSIDOMHTMLFIELDSETELEMENT // nsIContent - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; virtual nsresult InsertChildAt(nsIContent* aChild, uint32_t aIndex, bool aNotify) override; diff --git a/dom/html/HTMLFontElement.cpp b/dom/html/HTMLFontElement.cpp index 30cb9de8b..defba9126 100644 --- a/dom/html/HTMLFontElement.cpp +++ b/dom/html/HTMLFontElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLFontElement.h b/dom/html/HTMLFontElement.h index 3af54c3ef..b4bfd05e9 100644 --- a/dom/html/HTMLFontElement.h +++ b/dom/html/HTMLFontElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLFormControlsCollection.cpp b/dom/html/HTMLFormControlsCollection.cpp index 77fafae99..7d5d31b5f 100644 --- a/dom/html/HTMLFormControlsCollection.cpp +++ b/dom/html/HTMLFormControlsCollection.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLFormControlsCollection.h b/dom/html/HTMLFormControlsCollection.h index 1b8e1e62b..76e34ab4f 100644 --- a/dom/html/HTMLFormControlsCollection.h +++ b/dom/html/HTMLFormControlsCollection.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp index 6bea19a2b..2fe452bcd 100644 --- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -189,32 +188,37 @@ HTMLFormElement::GetElements(nsIDOMHTMLCollection** aElements) } nsresult -HTMLFormElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) -{ - if ((aName == nsGkAtoms::action || aName == nsGkAtoms::target) && - aNameSpaceID == kNameSpaceID_None) { - if (mPendingSubmission) { - // aha, there is a pending submission that means we're in - // the script and we need to flush it. let's tell it - // that the event was ignored to force the flush. - // the second argument is not playing a role at all. - FlushPendingSubmission(); +HTMLFormElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, bool aNotify) +{ + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::action || aName == nsGkAtoms::target) { + // This check is mostly to preserve previous behavior. + if (aValue) { + if (mPendingSubmission) { + // aha, there is a pending submission that means we're in + // the script and we need to flush it. let's tell it + // that the event was ignored to force the flush. + // the second argument is not playing a role at all. + FlushPendingSubmission(); + } + // Don't forget we've notified the password manager already if the + // page sets the action/target in the during submit. (bug 343182) + bool notifiedObservers = mNotifiedObservers; + ForgetCurrentSubmission(); + mNotifiedObservers = notifiedObservers; + } } - // Don't forget we've notified the password manager already if the - // page sets the action/target in the during submit. (bug 343182) - bool notifiedObservers = mNotifiedObservers; - ForgetCurrentSubmission(); - mNotifiedObservers = notifiedObservers; } - return nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, - aNotify); + + return nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, aValue, + aNotify); } nsresult HTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aName == nsGkAtoms::novalidate && aNameSpaceID == kNameSpaceID_None) { // Update all form elements states because they might be [no longer] @@ -230,7 +234,8 @@ HTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } } - return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify); + return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, + aOldValue, aNotify); } NS_IMPL_STRING_ATTR(HTMLFormElement, AcceptCharset, acceptcharset) @@ -489,7 +494,7 @@ HTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent) } nsresult -HTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLFormElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mWantsWillHandleEvent = true; if (aVisitor.mEvent->mOriginalTarget == static_cast<nsIContent*>(this)) { @@ -513,7 +518,7 @@ HTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor) mGeneratingReset = true; } } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } nsresult diff --git a/dom/html/HTMLFormElement.h b/dom/html/HTMLFormElement.h index b3e836f5f..f13eab9ac 100644 --- a/dom/html/HTMLFormElement.h +++ b/dom/html/HTMLFormElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -93,7 +92,8 @@ public: nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult) override; - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult WillHandleEvent( EventChainPostVisitor& aVisitor) override; virtual nsresult PostHandleEvent( @@ -104,16 +104,13 @@ public: bool aCompileEventHandlers) override; virtual void UnbindFromTree(bool aDeep = true, bool aNullParent = true) override; - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; + virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; /** * Forget all information about the current submission (and the fact that we diff --git a/dom/html/HTMLFormSubmission.cpp b/dom/html/HTMLFormSubmission.cpp index d6269a7ca..d447f5147 100644 --- a/dom/html/HTMLFormSubmission.cpp +++ b/dom/html/HTMLFormSubmission.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLFormSubmission.h b/dom/html/HTMLFormSubmission.h index 2a07143c7..506aa668d 100644 --- a/dom/html/HTMLFormSubmission.h +++ b/dom/html/HTMLFormSubmission.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLFormSubmissionConstants.h b/dom/html/HTMLFormSubmissionConstants.h index 860083d88..261af6165 100644 --- a/dom/html/HTMLFormSubmissionConstants.h +++ b/dom/html/HTMLFormSubmissionConstants.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLFrameElement.cpp b/dom/html/HTMLFrameElement.cpp index 989022b0c..0dc20019f 100644 --- a/dom/html/HTMLFrameElement.cpp +++ b/dom/html/HTMLFrameElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLFrameElement.h b/dom/html/HTMLFrameElement.h index c5a7120b3..31b07c03e 100644 --- a/dom/html/HTMLFrameElement.h +++ b/dom/html/HTMLFrameElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLFrameSetElement.cpp b/dom/html/HTMLFrameSetElement.cpp index 5d49cd78e..75fd14ba4 100644 --- a/dom/html/HTMLFrameSetElement.cpp +++ b/dom/html/HTMLFrameSetElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -10,6 +9,7 @@ #include "nsContentUtils.h" #include "nsGlobalWindow.h" #include "mozilla/UniquePtrExtensions.h" +#include "nsAttrValueOrString.h" NS_IMPL_NS_NEW_HTML_ELEMENT(FrameSet) @@ -66,43 +66,45 @@ HTMLFrameSetElement::GetRows(nsAString& aRows) } nsresult -HTMLFrameSetElement::SetAttr(int32_t aNameSpaceID, - nsIAtom* aAttribute, - nsIAtom* aPrefix, - const nsAString& aValue, - bool aNotify) +HTMLFrameSetElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) { - nsresult rv; /* The main goal here is to see whether the _number_ of rows or - * columns has changed. If it has, we need to reframe; otherwise - * we want to reflow. So we set mCurrentRowColHint here, then call - * nsGenericHTMLElement::SetAttr, which will end up calling - * GetAttributeChangeHint and notifying layout with that hint. - * Once nsGenericHTMLElement::SetAttr returns, we want to go back to our - * normal hint, which is NS_STYLE_HINT_REFLOW. + * columns has changed. If it has, we need to reframe; otherwise + * we want to reflow. + * Ideally, the style hint would be changed back to reflow after the reframe + * has been performed. Unfortunately, however, the reframe will be performed + * by the call to nsNodeUtils::AttributeChanged, which occurs *after* + * AfterSetAttr is called, leaving us with no convenient way of changing the + * value back to reflow afterwards. However, nsNodeUtils::AttributeChanged is + * effectively the only consumer of this value, so as long as we always set + * the value correctly here, we should be fine. */ - if (aAttribute == nsGkAtoms::rows && aNameSpaceID == kNameSpaceID_None) { - int32_t oldRows = mNumRows; - ParseRowCol(aValue, mNumRows, &mRowSpecs); + mCurrentRowColHint = NS_STYLE_HINT_REFLOW; + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::rows) { + if (aValue) { + int32_t oldRows = mNumRows; + ParseRowCol(aValue->String(), mNumRows, &mRowSpecs); - if (mNumRows != oldRows) { - mCurrentRowColHint = nsChangeHint_ReconstructFrame; - } - } else if (aAttribute == nsGkAtoms::cols && - aNameSpaceID == kNameSpaceID_None) { - int32_t oldCols = mNumCols; - ParseRowCol(aValue, mNumCols, &mColSpecs); + if (mNumRows != oldRows) { + mCurrentRowColHint = nsChangeHint_ReconstructFrame; + } + } + } else if (aName == nsGkAtoms::cols) { + if (aValue) { + int32_t oldCols = mNumCols; + ParseRowCol(aValue->String(), mNumCols, &mColSpecs); - if (mNumCols != oldCols) { - mCurrentRowColHint = nsChangeHint_ReconstructFrame; + if (mNumCols != oldCols) { + mCurrentRowColHint = nsChangeHint_ReconstructFrame; + } + } } } - rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aAttribute, aPrefix, - aValue, aNotify); - mCurrentRowColHint = NS_STYLE_HINT_REFLOW; - - return rv; + return nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, aValue, aNotify); } nsresult diff --git a/dom/html/HTMLFrameSetElement.h b/dom/html/HTMLFrameSetElement.h index b6bbe5d95..bede651d2 100644 --- a/dom/html/HTMLFrameSetElement.h +++ b/dom/html/HTMLFrameSetElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -100,17 +99,6 @@ public: #undef WINDOW_EVENT_HELPER #undef EVENT - // These override the SetAttr methods in nsGenericHTMLElement (need - // both here to silence compiler warnings). - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - /** * GetRowSpec is used to get the "rows" spec. * @param out int32_t aNumValues The number of row sizes specified. @@ -143,6 +131,10 @@ protected: virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override; + virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) override; + private: nsresult ParseRowCol(const nsAString& aValue, int32_t& aNumSpecs, diff --git a/dom/html/HTMLHRElement.cpp b/dom/html/HTMLHRElement.cpp index fb5dbe618..9779028ae 100644 --- a/dom/html/HTMLHRElement.cpp +++ b/dom/html/HTMLHRElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLHRElement.h b/dom/html/HTMLHRElement.h index c06a473bd..6f6213d76 100644 --- a/dom/html/HTMLHRElement.h +++ b/dom/html/HTMLHRElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLHeadingElement.cpp b/dom/html/HTMLHeadingElement.cpp index 091e60abb..b9ae86cac 100644 --- a/dom/html/HTMLHeadingElement.cpp +++ b/dom/html/HTMLHeadingElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLHeadingElement.h b/dom/html/HTMLHeadingElement.h index 2abf5bbb5..b42fcb9b1 100644 --- a/dom/html/HTMLHeadingElement.h +++ b/dom/html/HTMLHeadingElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLIFrameElement.cpp b/dom/html/HTMLIFrameElement.cpp index 0d5a209c0..8cf19dc9f 100644 --- a/dom/html/HTMLIFrameElement.cpp +++ b/dom/html/HTMLIFrameElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -182,54 +181,49 @@ HTMLIFrameElement::GetAttributeMappingFunction() const } nsresult -HTMLIFrameElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) -{ - nsresult rv = nsGenericHTMLFrameElement::SetAttr(aNameSpaceID, aName, - aPrefix, aValue, aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::srcdoc) { - // Don't propagate error here. The attribute was successfully set, that's - // what we should reflect. - LoadSrc(); - } - - return NS_OK; -} - -nsresult HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - bool aNotify) + const nsAttrValue* aOldValue, bool aNotify) { - if (aName == nsGkAtoms::sandbox && - aNameSpaceID == kNameSpaceID_None && mFrameLoader) { - // If we have an nsFrameLoader, apply the new sandbox flags. - // Since this is called after the setter, the sandbox flags have - // alreay been updated. - mFrameLoader->ApplySandboxFlags(GetSandboxFlags()); + AfterMaybeChangeAttr(aNameSpaceID, aName, aNotify); + + if (aNameSpaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::sandbox) { + if (mFrameLoader) { + // If we have an nsFrameLoader, apply the new sandbox flags. + // Since this is called after the setter, the sandbox flags have + // alreay been updated. + mFrameLoader->ApplySandboxFlags(GetSandboxFlags()); + } + } } return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aNotify); + aOldValue, aNotify); } nsresult -HTMLIFrameElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) +HTMLIFrameElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) { - // Invoke on the superclass. - nsresult rv = nsGenericHTMLFrameElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - if (aNameSpaceID == kNameSpaceID_None && - aAttribute == nsGkAtoms::srcdoc) { - // Fall back to the src attribute, if any - LoadSrc(); - } + AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); + + return nsGenericHTMLFrameElement::OnAttrSetButNotChanged(aNamespaceID, aName, + aValue, aNotify); +} - return NS_OK; +void +HTMLIFrameElement::AfterMaybeChangeAttr(int32_t aNamespaceID, + nsIAtom* aName, + bool aNotify) +{ + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::srcdoc) { + // Don't propagate errors from LoadSrc. The attribute was successfully + // set/unset, that's what we should reflect. + LoadSrc(); + } + } } uint32_t diff --git a/dom/html/HTMLIFrameElement.h b/dom/html/HTMLIFrameElement.h index 5bfda2470..e1240de81 100644 --- a/dom/html/HTMLIFrameElement.h +++ b/dom/html/HTMLIFrameElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -46,20 +45,6 @@ public: virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, - bool aNotify) override; - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) override; - uint32_t GetSandboxFlags(); // Web IDL binding methods @@ -196,11 +181,30 @@ protected: virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; + virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; + virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) override; + private: static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData); static const DOMTokenListSupportedToken sSupportedSandboxTokens[]; + + /** + * This function is called by AfterSetAttr and OnAttrSetButNotChanged. + * This function will be called by AfterSetAttr whether the attribute is being + * set or unset. + * + * @param aNamespaceID the namespace of the attr being set + * @param aName the localname of the attribute being set + * @param aNotify Whether we plan to notify document observers. + */ + void AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, bool aNotify); }; } // namespace dom diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp index 08f2404ce..5e75d0934 100644 --- a/dom/html/HTMLImageElement.cpp +++ b/dom/html/HTMLImageElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -112,6 +111,7 @@ private: HTMLImageElement::HTMLImageElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) : nsGenericHTMLElement(aNodeInfo) , mForm(nullptr) + , mForceReload(false) , mInDocResponsiveContent(false) , mCurrentDensity(1.0) { @@ -369,9 +369,12 @@ HTMLImageElement::GetAttributeMappingFunction() const nsresult HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) { + if (aValue) { + BeforeMaybeChangeAttr(aNameSpaceID, aName, *aValue, aNotify); + } if (aNameSpaceID == kNameSpaceID_None && mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id)) { @@ -391,8 +394,13 @@ HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { + if (aValue) { + AfterMaybeChangeAttr(aNameSpaceID, aName, aNotify); + } + if (aNameSpaceID == kNameSpaceID_None && mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id) && aValue && !aValue->IsEmptyString()) { @@ -433,67 +441,26 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, - aValue, aNotify); + aValue, aOldValue, aNotify); } nsresult -HTMLImageElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLImageElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) { - // We handle image element with attribute ismap in its corresponding frame - // element. Set mMultipleActionsPrevented here to prevent the click event - // trigger the behaviors in Element::PostHandleEventForLinks - WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent(); - if (mouseEvent && mouseEvent->IsLeftClickEvent() && IsMap()) { - mouseEvent->mFlags.mMultipleActionsPrevented = true; - } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); -} - -bool -HTMLImageElement::IsHTMLFocusable(bool aWithMouse, - bool *aIsFocusable, int32_t *aTabIndex) -{ - int32_t tabIndex = TabIndex(); - - if (IsInUncomposedDoc()) { - nsAutoString usemap; - GetUseMap(usemap); - // XXXbz which document should this be using? sXBL/XBL2 issue! I - // think that OwnerDoc() is right, since we don't want to - // assume stuff about the document we're bound to. - if (OwnerDoc()->FindImageMap(usemap)) { - if (aTabIndex) { - // Use tab index on individual map areas - *aTabIndex = (sTabFocusModel & eTabFocus_linksMask)? 0 : -1; - } - // Image map is not focusable itself, but flag as tabbable - // so that image map areas get walked into. - *aIsFocusable = false; - - return false; - } - } - - if (aTabIndex) { - // Can be in tab order if tabindex >=0 and form controls are tabbable. - *aTabIndex = (sTabFocusModel & eTabFocus_formElementsMask)? tabIndex : -1; - } + BeforeMaybeChangeAttr(aNamespaceID, aName, aValue, aNotify); + AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); - *aIsFocusable = -#ifdef XP_MACOSX - (!aWithMouse || nsFocusManager::sMouseFocusesFormControl) && -#endif - (tabIndex >= 0 || HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)); - - return false; + return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName, + aValue, aNotify); } -nsresult -HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) +void +HTMLImageElement::BeforeMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) { - bool forceReload = false; // We need to force our image to reload. This must be done here, not in // AfterSetAttr or BeforeSetAttr, because we want to do it even if the attr is // being set to its existing value, which is normally optimized away as a @@ -504,16 +471,19 @@ HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, // spec. // // Both cases handle unsetting src in AfterSetAttr - if (aNameSpaceID == kNameSpaceID_None && + // + // Much of this should probably happen in AfterMaybeChangeAttr. + // See Bug 1370705 + if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { if (InResponsiveMode()) { if (mResponsiveSelector && mResponsiveSelector->Content() == this) { - mResponsiveSelector->SetDefaultSource(aValue); + mResponsiveSelector->SetDefaultSource(aValue.String()); } QueueImageLoadTask(true); - } else if (aNotify) { + } else if (aNotify && OwnerDoc()->IsCurrentActiveDocument()) { // If aNotify is false, we are coming from the parser or some such place; // we'll get bound after all the attributes have been set, so we'll do the // sync image load from BindToTree. Skip the LoadImage call in that case. @@ -528,23 +498,23 @@ HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, // the state gets in Element's attr-setting happen around this // LoadImage call, we could start passing false instead of aNotify // here. - LoadImage(aValue, true, aNotify, eImageLoadType_Normal); + LoadImage(aValue.String(), true, aNotify, eImageLoadType_Normal); mNewRequestsWillNeedAnimationReset = false; } - } else if (aNameSpaceID == kNameSpaceID_None && + } else if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::crossorigin && aNotify) { nsAttrValue attrValue; - ParseCORSValue(aValue, attrValue); + ParseCORSValue(aValue.String(), attrValue); if (GetCORSMode() != AttrValueToCORSMode(&attrValue)) { // Force a new load of the image with the new cross origin policy. - forceReload = true; + mForceReload = true; } } else if (aName == nsGkAtoms::referrerpolicy && - aNameSpaceID == kNameSpaceID_None && + aNamespaceID == kNameSpaceID_None && aNotify) { - ReferrerPolicy referrerPolicy = AttributeReferrerPolicyFromString(aValue); + ReferrerPolicy referrerPolicy = AttributeReferrerPolicyFromString(aValue.String()); if (!InResponsiveMode() && referrerPolicy != RP_Unset && referrerPolicy != GetImageReferrerPolicy()) { @@ -553,22 +523,28 @@ HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, // the attribute will neither trigger a reload nor update the referrer // policy of the loading channel (whether it has previously completed or // not). Force a new load of the image with the new referrerpolicy. - forceReload = true; + mForceReload = true; } } - nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, - aValue, aNotify); + return; +} +void +HTMLImageElement::AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + bool aNotify) +{ // Because we load image synchronously in non-responsive-mode, we need to do // reload after the attribute has been set if the reload is triggerred by // cross origin changing. - if (forceReload) { + if (mForceReload) { + mForceReload = false; + if (InResponsiveMode()) { // per spec, full selection runs when this changes, even though // it doesn't directly affect the source selection QueueImageLoadTask(true); - } else { + } else if (OwnerDoc()->IsCurrentActiveDocument()) { // Bug 1076583 - We still use the older synchronous algorithm in // non-responsive mode. Force a new load of the image with the // new cross origin policy @@ -576,7 +552,59 @@ HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, } } - return rv; + return; +} + +nsresult +HTMLImageElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) +{ + // We handle image element with attribute ismap in its corresponding frame + // element. Set mMultipleActionsPrevented here to prevent the click event + // trigger the behaviors in Element::PostHandleEventForLinks + WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent(); + if (mouseEvent && mouseEvent->IsLeftClickEvent() && IsMap()) { + mouseEvent->mFlags.mMultipleActionsPrevented = true; + } + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); +} + +bool +HTMLImageElement::IsHTMLFocusable(bool aWithMouse, + bool *aIsFocusable, int32_t *aTabIndex) +{ + int32_t tabIndex = TabIndex(); + + if (IsInUncomposedDoc()) { + nsAutoString usemap; + GetUseMap(usemap); + // XXXbz which document should this be using? sXBL/XBL2 issue! I + // think that OwnerDoc() is right, since we don't want to + // assume stuff about the document we're bound to. + if (OwnerDoc()->FindImageMap(usemap)) { + if (aTabIndex) { + // Use tab index on individual map areas + *aTabIndex = (sTabFocusModel & eTabFocus_linksMask)? 0 : -1; + } + // Image map is not focusable itself, but flag as tabbable + // so that image map areas get walked into. + *aIsFocusable = false; + + return false; + } + } + + if (aTabIndex) { + // Can be in tab order if tabindex >=0 and form controls are tabbable. + *aTabIndex = (sTabFocusModel & eTabFocus_formElementsMask)? tabIndex : -1; + } + + *aIsFocusable = +#ifdef XP_MACOSX + (!aWithMouse || nsFocusManager::sMouseFocusesFormControl) && +#endif + (tabIndex >= 0 || HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)); + + return false; } nsresult diff --git a/dom/html/HTMLImageElement.h b/dom/html/HTMLImageElement.h index 1e63cd79c..8d382610d 100644 --- a/dom/html/HTMLImageElement.h +++ b/dom/html/HTMLImageElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -70,21 +69,11 @@ public: NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override; virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override; - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override; - // SetAttr override. C++ is stupid, so have to override both - // overloaded methods. - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers) override; @@ -348,11 +337,17 @@ protected: void UpdateFormOwner(); virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; + + virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) override; // This is a weak reference that this element and the HTMLFormElement // cooperate in maintaining. @@ -367,6 +362,36 @@ private: static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData); + /** + * This function is called by BeforeSetAttr and OnAttrSetButNotChanged. + * It will not be called if the value is being unset. + * + * @param aNamespaceID the namespace of the attr being set + * @param aName the localname of the attribute being set + * @param aValue the value it's being set to represented as either a string or + * a parsed nsAttrValue. + * @param aNotify Whether we plan to notify document observers. + */ + void BeforeMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify); + /** + * This function is called by AfterSetAttr and OnAttrSetButNotChanged. + * It will not be called if the value is being unset. + * + * @param aNamespaceID the namespace of the attr being set + * @param aName the localname of the attribute being set + * @param aNotify Whether we plan to notify document observers. + */ + void AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + bool aNotify); + /** + * Used by BeforeMaybeChangeAttr and AfterMaybeChangeAttr to keep track of + * whether a reload needs to be forced after an attribute change that is + * currently in progress. + */ + bool mForceReload; + bool mInDocResponsiveContent; RefPtr<ImageLoadTask> mPendingImageLoadTask; diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 7a07994f7..86d03d8f5 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -147,6 +146,8 @@ namespace dom { #define NS_CONTROL_TYPE(bits) ((bits) & ~( \ NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | NS_NO_CONTENT_DISPATCH | \ NS_ORIGINAL_INDETERMINATE_VALUE)) +#define NS_PRE_HANDLE_BLUR_EVENT (1 << 13) +#define NS_PRE_HANDLE_INPUT_EVENT (1 << 14) // whether textfields should be selected once focused: // -1: no, 1: yes, 0: uninitialized @@ -172,15 +173,18 @@ static const nsAttrValue::EnumTable kInputTypeTable[] = { { "search", NS_FORM_INPUT_SEARCH }, { "submit", NS_FORM_INPUT_SUBMIT }, { "tel", NS_FORM_INPUT_TEL }, - { "text", NS_FORM_INPUT_TEXT }, { "time", NS_FORM_INPUT_TIME }, { "url", NS_FORM_INPUT_URL }, { "week", NS_FORM_INPUT_WEEK }, + // "text" must be last for ParseAttribute to work right. If you add things + // before it, please update kInputDefaultType. + { "text", NS_FORM_INPUT_TEXT }, { nullptr, 0 } }; // Default type is 'text'. -static const nsAttrValue::EnumTable* kInputDefaultType = &kInputTypeTable[18]; +static const nsAttrValue::EnumTable* kInputDefaultType = + &kInputTypeTable[ArrayLength(kInputTypeTable) - 2]; static const uint8_t NS_INPUT_INPUTMODE_AUTO = 0; static const uint8_t NS_INPUT_INPUTMODE_NUMERIC = 1; @@ -1235,7 +1239,7 @@ HTMLInputElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) co nsresult HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { @@ -1259,10 +1263,6 @@ HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } } else if (aNotify && aName == nsGkAtoms::disabled) { mDisabledChanged = true; - } else if (aName == nsGkAtoms::dir && - AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir, - nsGkAtoms::_auto, eIgnoreCase)) { - SetDirectionIfAuto(false, aNotify); } else if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) { nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer(); @@ -1282,7 +1282,8 @@ HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { // @@ -1322,36 +1323,15 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } if (aName == nsGkAtoms::type) { + uint8_t newType; if (!aValue) { - // We're now a text input. Note that we have to handle this manually, - // since removing an attribute (which is what happened, since aValue is - // null) doesn't call ParseAttribute. - HandleTypeChange(kInputDefaultType->value); - } - - UpdateBarredFromConstraintValidation(); - - if (mType != NS_FORM_INPUT_IMAGE) { - // We're no longer an image input. Cancel our image requests, if we have - // any. Note that doing this when we already weren't an image is ok -- - // just does nothing. - 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)) { - LoadImage(src, false, aNotify, eImageLoadType_Normal); - } + // We're now a text input. + newType = kInputDefaultType->value; + } else { + newType = aValue->GetEnumValue(); } - - if (mType == NS_FORM_INPUT_PASSWORD && IsInComposedDoc()) { - AsyncEventDispatcher* dispatcher = - new AsyncEventDispatcher(this, - NS_LITERAL_STRING("DOMInputPasswordAdded"), - true, - true); - dispatcher->PostDOMEvent(); + if (newType != mType) { + HandleTypeChange(newType, aNotify); } } @@ -1434,7 +1414,7 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, "HTML5 spec does not allow underflow for type=range"); } else if (aName == nsGkAtoms::dir && aValue && aValue->Equals(nsGkAtoms::_auto, eIgnoreCase)) { - SetDirectionIfAuto(true, aNotify); + SetDirectionFromValue(aNotify); } else if (aName == nsGkAtoms::lang) { if (mType == NS_FORM_INPUT_NUMBER) { // Update the value that is displayed to the user to the new locale: @@ -1450,12 +1430,11 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, // Clear the cached @autocomplete attribute state. mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown; } - - UpdateState(aNotify); } return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, - aValue, aNotify); + aValue, aOldValue, + aNotify); } // nsIDOMHTMLInputElement @@ -3738,7 +3717,7 @@ HTMLInputElement::IsDisabledForEvents(WidgetEvent* aEvent) } nsresult -HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLInputElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { // Do not process any DOM events if the element is disabled aVisitor.mCanHandle = false; @@ -3755,7 +3734,7 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) //FIXME Allow submission etc. also when there is no prescontext, Bug 329509. if (!aVisitor.mPresContext) { - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor); } // // Web pages expect the value of a radio button or checkbox to be set @@ -3865,23 +3844,16 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) // Fire onchange (if necessary), before we do the blur, bug 357684. if (aVisitor.mEvent->mMessage == eBlur) { - // Experimental mobile types rely on the system UI to prevent users to not - // set invalid values but we have to be extra-careful. Especially if the - // option has been enabled on desktop. - if (IsExperimentalMobileType(mType)) { - nsAutoString aValue; - GetValueInternal(aValue); - nsresult rv = - SetValueInternal(aValue, nsTextEditorState::eSetValue_Internal); - NS_ENSURE_SUCCESS(rv, rv); - } - FireChangeEventIfNeeded(); + // We set NS_PRE_HANDLE_BLUR_EVENT here and handle it in PreHandleEvent to + // prevent breaking event target chain creation. + aVisitor.mWantsPreHandleEvent = true; + aVisitor.mItemFlags |= NS_PRE_HANDLE_BLUR_EVENT; } if (mType == NS_FORM_INPUT_RANGE && (aVisitor.mEvent->mMessage == eFocus || aVisitor.mEvent->mMessage == eBlur)) { - // Just as nsGenericHTMLFormElementWithState::PreHandleEvent calls + // Just as nsGenericHTMLFormElementWithState::GetEventTargetParent calls // nsIFormControlFrame::SetFocus, we handle focus here. nsIFrame* frame = GetPrimaryFrame(); if (frame) { @@ -3969,10 +3941,11 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) } } - nsresult rv = nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor); + nsresult rv = nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor); - // We do this after calling the base class' PreHandleEvent so that - // nsIContent::PreHandleEvent doesn't reset any change we make to mCanHandle. + // We do this after calling the base class' GetEventTargetParent so that + // nsIContent::GetEventTargetParent doesn't reset any change we make to + // mCanHandle. if (mType == NS_FORM_INPUT_NUMBER && aVisitor.mEvent->IsTrusted() && aVisitor.mEvent->mOriginalTarget != this) { @@ -3987,18 +3960,10 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) } if (textControl && aVisitor.mEvent->mOriginalTarget == textControl) { if (aVisitor.mEvent->mMessage == eEditorInput) { - // Propogate the anon text control's new value to our HTMLInputElement: - nsAutoString value; - numberControlFrame->GetValueOfAnonTextControl(value); - numberControlFrame->HandlingInputEvent(true); - nsWeakFrame weakNumberControlFrame(numberControlFrame); - rv = SetValueInternal(value, - nsTextEditorState::eSetValue_BySetUserInput | - nsTextEditorState::eSetValue_Notify); - NS_ENSURE_SUCCESS(rv, rv); - if (weakNumberControlFrame.IsAlive()) { - numberControlFrame->HandlingInputEvent(false); - } + aVisitor.mWantsPreHandleEvent = true; + // We set NS_PRE_HANDLE_INPUT_EVENT here and handle it in PreHandleEvent + // to prevent breaking event target chain creation. + aVisitor.mItemFlags |= NS_PRE_HANDLE_INPUT_EVENT; } else if (aVisitor.mEvent->mMessage == eFormChange) { // We cancel the DOM 'change' event that is fired for any change to our @@ -4037,6 +4002,50 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) return rv; } +nsresult +HTMLInputElement::PreHandleEvent(EventChainVisitor& aVisitor) +{ + if (!aVisitor.mPresContext) { + return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor); + } + nsresult rv; + if (aVisitor.mItemFlags & NS_PRE_HANDLE_BLUR_EVENT) { + MOZ_ASSERT(aVisitor.mEvent->mMessage == eBlur); + // Experimental mobile types rely on the system UI to prevent users to not + // set invalid values but we have to be extra-careful. Especially if the + // option has been enabled on desktop. + if (IsExperimentalMobileType(mType)) { + nsAutoString aValue; + GetValueInternal(aValue); + nsresult rv = + SetValueInternal(aValue, nsTextEditorState::eSetValue_Internal); + NS_ENSURE_SUCCESS(rv, rv); + } + FireChangeEventIfNeeded(); + } + rv = nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor); + if (aVisitor.mItemFlags & NS_PRE_HANDLE_INPUT_EVENT) { + nsNumberControlFrame* numberControlFrame = do_QueryFrame(GetPrimaryFrame()); + MOZ_ASSERT(aVisitor.mEvent->mMessage == eEditorInput); + MOZ_ASSERT(numberControlFrame); + MOZ_ASSERT(numberControlFrame->GetAnonTextControl() == + aVisitor.mEvent->mOriginalTarget); + // Propogate the anon text control's new value to our HTMLInputElement: + nsAutoString value; + numberControlFrame->GetValueOfAnonTextControl(value); + numberControlFrame->HandlingInputEvent(true); + nsWeakFrame weakNumberControlFrame(numberControlFrame); + rv = SetValueInternal(value, + nsTextEditorState::eSetValue_BySetUserInput | + nsTextEditorState::eSetValue_Notify); + NS_ENSURE_SUCCESS(rv, rv); + if (weakNumberControlFrame.IsAlive()) { + numberControlFrame->HandlingInputEvent(false); + } + } + return rv; +} + void HTMLInputElement::StartRangeThumbDrag(WidgetGUIEvent* aEvent) { @@ -4961,7 +4970,9 @@ HTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, } // Set direction based on value if dir=auto - SetDirectionIfAuto(HasDirAuto(), false); + if (HasDirAuto()) { + SetDirectionFromValue(false); + } // An element can't suffer from value missing if it is not in a document. // We have to check if we suffer from that as we are now in a document. @@ -5015,14 +5026,23 @@ HTMLInputElement::UnbindFromTree(bool aDeep, bool aNullParent) } void -HTMLInputElement::HandleTypeChange(uint8_t aNewType) +HTMLInputElement::HandleTypeChange(uint8_t aNewType, bool aNotify) { - if (mType == NS_FORM_INPUT_RANGE && mIsDraggingRange) { + uint8_t oldType = mType; + MOZ_ASSERT(oldType != aNewType); + + if (aNewType == NS_FORM_INPUT_FILE || oldType == NS_FORM_INPUT_FILE) { + // Strictly speaking, we only need to clear files on going _to_ or _from_ + // the NS_FORM_INPUT_FILE type, not both, since we'll never confuse values + // and filenames. But this is safer. + ClearFiles(false); + } + + if (oldType == NS_FORM_INPUT_RANGE && mIsDraggingRange) { CancelRangeThumbDrag(false); } ValueModeType aOldValueMode = GetValueMode(); - uint8_t oldType = mType; nsAutoString aOldValue; if (aOldValueMode == VALUE_MODE_VALUE) { @@ -5103,6 +5123,30 @@ HTMLInputElement::HandleTypeChange(uint8_t aNewType) UpdateAllValidityStates(false); UpdateApzAwareFlag(); + + UpdateBarredFromConstraintValidation(); + + if (oldType == NS_FORM_INPUT_IMAGE) { + // We're no longer an image input. Cancel our image requests, if we have + // any. + CancelImageRequests(aNotify); + } else if (aNotify && mType == NS_FORM_INPUT_IMAGE) { + // 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)) { + LoadImage(src, false, aNotify, eImageLoadType_Normal); + } + } + + if (mType == NS_FORM_INPUT_PASSWORD && IsInComposedDoc()) { + AsyncEventDispatcher* dispatcher = + new AsyncEventDispatcher(this, + NS_LITERAL_STRING("DOMInputPasswordAdded"), + true, + true); + dispatcher->PostDOMEvent(); + } } void @@ -5813,42 +5857,32 @@ HTMLInputElement::ParseAttribute(int32_t aNamespaceID, const nsAString& aValue, nsAttrValue& aResult) { + MOZ_ASSERT(kInputDefaultType->value == NS_FORM_INPUT_TEXT, + "Someone forgot to update kInputDefaultType when adding a new " + "input type."); + MOZ_ASSERT(kInputTypeTable[ArrayLength(kInputTypeTable) - 1].tag == nullptr, + "Last entry in the table must be the nullptr guard"); + MOZ_ASSERT(kInputTypeTable[ArrayLength(kInputTypeTable) - 2].value == + NS_FORM_INPUT_TEXT, + "Next to last entry in the table must be the \"text\" entry"); + if (aNamespaceID == kNameSpaceID_None) { if (aAttribute == nsGkAtoms::type) { - // XXX ARG!! This is major evilness. ParseAttribute - // shouldn't set members. Override SetAttr instead - int32_t newType; - bool success = aResult.ParseEnumValue(aValue, kInputTypeTable, false); - if (success) { - newType = aResult.GetEnumValue(); - if ((newType == NS_FORM_INPUT_NUMBER && !IsInputNumberEnabled()) || - (newType == NS_FORM_INPUT_COLOR && !IsInputColorEnabled()) || - (IsDateTimeInputType(newType) && !IsDateTimeTypeSupported(newType))) { - newType = kInputDefaultType->value; - aResult.SetTo(newType, &aValue); - } - } else { - newType = kInputDefaultType->value; + aResult.ParseEnumValue(aValue, kInputTypeTable, false, kInputDefaultType); + int32_t newType = aResult.GetEnumValue(); + if ((IsExperimentalMobileType(newType) && + !IsExperimentalFormsEnabled()) || + (newType == NS_FORM_INPUT_NUMBER && !IsInputNumberEnabled()) || + (newType == NS_FORM_INPUT_COLOR && !IsInputColorEnabled()) || + (IsDateTimeInputType(newType) && + !IsDateTimeTypeSupported(newType))) { + // There's no public way to set an nsAttrValue to an enum value, but we + // can just re-parse with a table that doesn't have any types other than + // "text" in it. + aResult.ParseEnumValue(aValue, kInputDefaultType, false, kInputDefaultType); } - if (newType != mType) { - // Make sure to do the check for newType being NS_FORM_INPUT_FILE and - // the corresponding SetValueInternal() call _before_ we set mType. - // That way the logic in SetValueInternal() will work right (that logic - // makes assumptions about our frame based on mType, but we won't have - // had time to recreate frames yet -- that happens later in the - // SetAttr() process). - if (newType == NS_FORM_INPUT_FILE || mType == NS_FORM_INPUT_FILE) { - // This call isn't strictly needed any more since we'll never - // confuse values and filenames. However it's there for backwards - // compat. - ClearFiles(false); - } - - HandleTypeChange(newType); - } - - return success; + return true; } if (aAttribute == nsGkAtoms::width) { return aResult.ParseSpecialIntValue(aValue); @@ -6654,17 +6688,12 @@ HTMLInputElement::SetDefaultValueAsValue() } void -HTMLInputElement::SetDirectionIfAuto(bool aAuto, bool aNotify) +HTMLInputElement::SetDirectionFromValue(bool aNotify) { - if (aAuto) { - SetHasDirAuto(); - if (IsSingleLineTextControl(true)) { - nsAutoString value; - GetValue(value); - SetDirectionalityFromValue(this, value, aNotify); - } - } else { - ClearHasDirAuto(); + if (IsSingleLineTextControl(true)) { + nsAutoString value; + GetValue(value); + SetDirectionalityFromValue(this, value, aNotify); } } @@ -8441,7 +8470,7 @@ HTMLInputElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) UpdateAllValidityStates(aNotify); if (HasDirAuto()) { - SetDirectionIfAuto(true, aNotify); + SetDirectionFromValue(aNotify); } // :placeholder-shown pseudo-class may change when the value changes. diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h index a000aa21d..16651d520 100644 --- a/dom/html/HTMLInputElement.h +++ b/dom/html/HTMLInputElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -185,7 +184,9 @@ public: NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override; virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override; - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; + virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; void PostHandleEventForRangeThumb(EventChainPostVisitor& aVisitor); @@ -956,13 +957,15 @@ protected: * Called when an attribute is about to be changed */ virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) override; /** * Called when an attribute has just been changed */ virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; /** * Dispatch a select event. Returns true if the event was not cancelled. @@ -1098,7 +1101,7 @@ protected: /** * Manages the internal data storage across type changes. */ - void HandleTypeChange(uint8_t aNewType); + void HandleTypeChange(uint8_t aNewType, bool aNotify); /** * Sanitize the value of the element depending of its current type. @@ -1118,7 +1121,7 @@ protected: */ nsresult SetDefaultValueAsValue(); - virtual void SetDirectionIfAuto(bool aAuto, bool aNotify); + void SetDirectionFromValue(bool aNotify); /** * Return if an element should have a specific validity UI diff --git a/dom/html/HTMLLIElement.cpp b/dom/html/HTMLLIElement.cpp index 304105399..8b1e8df8e 100644 --- a/dom/html/HTMLLIElement.cpp +++ b/dom/html/HTMLLIElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLLIElement.h b/dom/html/HTMLLIElement.h index 3f5692009..f631966a3 100644 --- a/dom/html/HTMLLIElement.h +++ b/dom/html/HTMLLIElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLLabelElement.cpp b/dom/html/HTMLLabelElement.cpp index ec36c8b99..00df4b5d9 100644 --- a/dom/html/HTMLLabelElement.cpp +++ b/dom/html/HTMLLabelElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLLabelElement.h b/dom/html/HTMLLabelElement.h index c8385fc53..5771a001f 100644 --- a/dom/html/HTMLLabelElement.h +++ b/dom/html/HTMLLabelElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLLegendElement.cpp b/dom/html/HTMLLegendElement.cpp index 1a593d769..87df3ba3e 100644 --- a/dom/html/HTMLLegendElement.cpp +++ b/dom/html/HTMLLegendElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -71,21 +70,6 @@ HTMLLegendElement::GetAttributeChangeHint(const nsIAtom* aAttribute, } nsresult -HTMLLegendElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) -{ - return nsGenericHTMLElement::SetAttr(aNameSpaceID, aAttribute, - aPrefix, aValue, aNotify); -} -nsresult -HTMLLegendElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) -{ - return nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); -} - -nsresult HTMLLegendElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers) diff --git a/dom/html/HTMLLegendElement.h b/dom/html/HTMLLegendElement.h index e2d71d62d..6ce3140ec 100644 --- a/dom/html/HTMLLegendElement.h +++ b/dom/html/HTMLLegendElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -42,16 +41,6 @@ public: nsAttrValue& aResult) override; virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, int32_t aModType) const override; - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) override; virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override; diff --git a/dom/html/HTMLLinkElement.cpp b/dom/html/HTMLLinkElement.cpp index 1b78cbd69..df0cc72a4 100644 --- a/dom/html/HTMLLinkElement.cpp +++ b/dom/html/HTMLLinkElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -344,7 +343,7 @@ HTMLLinkElement::UpdateImport() nsresult HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, bool aNotify) + const nsAttrValueOrString* aValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None && (aName == nsGkAtoms::href || aName == nsGkAtoms::rel)) { @@ -359,7 +358,8 @@ HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { // It's safe to call ResetLinkState here because our new attr value has // already been set or unset. ResetLinkState needs the updated attribute @@ -436,13 +436,13 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aNotify); + aOldValue, aNotify); } nsresult -HTMLLinkElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLLinkElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { - return PreHandleEventForAnchors(aVisitor); + return GetEventTargetParentForAnchors(aVisitor); } nsresult diff --git a/dom/html/HTMLLinkElement.h b/dom/html/HTMLLinkElement.h index f9c832c8d..8575d5b49 100644 --- a/dom/html/HTMLLinkElement.h +++ b/dom/html/HTMLLinkElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -46,7 +45,8 @@ public: void UpdateImport(); // nsIDOMEventTarget - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; @@ -61,10 +61,11 @@ public: virtual void UnbindFromTree(bool aDeep = true, bool aNullParent = true) override; virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) override; virtual bool IsLink(nsIURI** aURI) const override; virtual already_AddRefed<nsIURI> GetHrefURI() const override; diff --git a/dom/html/HTMLMapElement.cpp b/dom/html/HTMLMapElement.cpp index 36a0f410b..b6d93e052 100644 --- a/dom/html/HTMLMapElement.cpp +++ b/dom/html/HTMLMapElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLMapElement.h b/dom/html/HTMLMapElement.h index a15bd6d23..03a9a9ae7 100644 --- a/dom/html/HTMLMapElement.h +++ b/dom/html/HTMLMapElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 4abc202a8..0828208f6 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -3738,77 +3737,74 @@ int32_t HTMLMediaElement::TabIndexDefault() return 0; } -nsresult HTMLMediaElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) -{ - nsresult rv = - nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, - aNotify); - if (NS_FAILED(rv)) - return rv; - if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { - DoLoad(); - } - if (aNotify && aNameSpaceID == kNameSpaceID_None) { - if (aName == nsGkAtoms::autoplay) { - StopSuspendingAfterFirstFrame(); - CheckAutoplayDataReady(); - // This attribute can affect AddRemoveSelfReference - AddRemoveSelfReference(); - UpdatePreloadAction(); +nsresult +HTMLMediaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) +{ + if (aNameSpaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::src) { + mSrcMediaSource = nullptr; + if (aValue) { + nsString srcStr = aValue->GetStringValue(); + nsCOMPtr<nsIURI> uri; + NewURIFromString(srcStr, getter_AddRefs(uri)); + if (uri && IsMediaSourceURI(uri)) { + nsresult rv = + NS_GetSourceForMediaSourceURI(uri, getter_AddRefs(mSrcMediaSource)); + if (NS_FAILED(rv)) { + nsAutoString spec; + GetCurrentSrc(spec); + const char16_t* params[] = { spec.get() }; + ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params)); + } + } + } + } else if (aName == nsGkAtoms::autoplay) { + if (aNotify) { + if (aValue) { + StopSuspendingAfterFirstFrame(); + CheckAutoplayDataReady(); + } + // This attribute can affect AddRemoveSelfReference + AddRemoveSelfReference(); + UpdatePreloadAction(); + } } else if (aName == nsGkAtoms::preload) { UpdatePreloadAction(); } } - return rv; + // Since AfterMaybeChangeAttr may call DoLoad, make sure that it is called + // *after* any possible changes to mSrcMediaSource. + if (aValue) { + AfterMaybeChangeAttr(aNameSpaceID, aName, aNotify); + } + + return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, + aValue, aOldValue, aNotify); } -nsresult HTMLMediaElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttr, - bool aNotify) +nsresult +HTMLMediaElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) { - nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttr, aNotify); - if (NS_FAILED(rv)) - return rv; - if (aNotify && aNameSpaceID == kNameSpaceID_None) { - if (aAttr == nsGkAtoms::autoplay) { - // This attribute can affect AddRemoveSelfReference - AddRemoveSelfReference(); - UpdatePreloadAction(); - } else if (aAttr == nsGkAtoms::preload) { - UpdatePreloadAction(); - } - } + AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); - return rv; + return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName, + aValue, aNotify); } -nsresult -HTMLMediaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) -{ - if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { - mSrcMediaSource = nullptr; - if (aValue) { - nsString srcStr = aValue->GetStringValue(); - nsCOMPtr<nsIURI> uri; - NewURIFromString(srcStr, getter_AddRefs(uri)); - if (uri && IsMediaSourceURI(uri)) { - nsresult rv = - NS_GetSourceForMediaSourceURI(uri, getter_AddRefs(mSrcMediaSource)); - if (NS_FAILED(rv)) { - nsAutoString spec; - GetCurrentSrc(spec); - const char16_t* params[] = { spec.get() }; - ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params)); - } - } +void +HTMLMediaElement::AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + bool aNotify) +{ + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::src) { + DoLoad(); } } - - return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, - aValue, aNotify); } nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, @@ -5646,7 +5642,7 @@ nsIContent* HTMLMediaElement::GetNextSource() "Should only iterate over direct children"); #endif - int32_t startOffset = 0; + uint32_t startOffset = 0; rv = mSourcePointer->GetStartOffset(&startOffset); NS_ENSURE_SUCCESS(rv, nullptr); diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h index 44c666f95..bda9924a6 100644 --- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -132,21 +131,6 @@ public: nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult) override; - // SetAttr override. C++ is stupid, so have to override both - // overloaded methods. - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttr, - bool aNotify) override; - virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, - bool aNotify) override; virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, @@ -1314,6 +1298,14 @@ protected: already_AddRefed<Promise> CreateDOMPromise(ErrorResult& aRv) const; + virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; + virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) override; + // The current decoder. Load() has been called on this decoder. // At most one of mDecoder and mSrcStream can be non-null. RefPtr<MediaDecoder> mDecoder; @@ -1716,6 +1708,17 @@ private: // We keep track of these because the load algorithm resolves/rejects all // already-dispatched pending play promises. nsTArray<nsResolveOrRejectPendingPlayPromisesRunner*> mPendingPlayPromisesRunners; + +private: + /** + * This function is called by AfterSetAttr and OnAttrSetButNotChanged. + * It will not be called if the value is being unset. + * + * @param aNamespaceID the namespace of the attr being set + * @param aName the localname of the attribute being set + * @param aNotify Whether we plan to notify document observers. + */ + void AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, bool aNotify); }; } // namespace dom diff --git a/dom/html/HTMLMenuElement.cpp b/dom/html/HTMLMenuElement.cpp index 098590f1b..6c096084a 100644 --- a/dom/html/HTMLMenuElement.cpp +++ b/dom/html/HTMLMenuElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLMenuElement.h b/dom/html/HTMLMenuElement.h index c374e7e60..5bd26fe98 100644 --- a/dom/html/HTMLMenuElement.h +++ b/dom/html/HTMLMenuElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLMenuItemElement.cpp b/dom/html/HTMLMenuItemElement.cpp index ca8bb4feb..5c5cf8d76 100644 --- a/dom/html/HTMLMenuItemElement.cpp +++ b/dom/html/HTMLMenuItemElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -252,7 +251,7 @@ HTMLMenuItemElement::SetChecked(bool aChecked) } nsresult -HTMLMenuItemElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLMenuItemElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { if (aVisitor.mEvent->mMessage == eMouseClick) { @@ -283,7 +282,7 @@ HTMLMenuItemElement::PreHandleEvent(EventChainPreVisitor& aVisitor) aVisitor.mItemFlags |= mType; } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } nsresult @@ -380,7 +379,8 @@ HTMLMenuItemElement::GetText(nsAString& aText) nsresult HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { if ((aName == nsGkAtoms::radiogroup || aName == nsGkAtoms::type) && @@ -404,7 +404,7 @@ HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aNotify); + aOldValue, aNotify); } void diff --git a/dom/html/HTMLMenuItemElement.h b/dom/html/HTMLMenuItemElement.h index 3c19b1170..1c738187c 100644 --- a/dom/html/HTMLMenuItemElement.h +++ b/dom/html/HTMLMenuItemElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -36,7 +35,8 @@ public: // nsIDOMHTMLMenuItemElement NS_DECL_NSIDOMHTMLMENUITEMELEMENT - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; @@ -124,7 +124,9 @@ protected: protected: virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; void WalkRadioGroup(Visitor* aVisitor); diff --git a/dom/html/HTMLMetaElement.cpp b/dom/html/HTMLMetaElement.cpp index de7dc184c..f0a66b52c 100644 --- a/dom/html/HTMLMetaElement.cpp +++ b/dom/html/HTMLMetaElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -61,7 +60,8 @@ HTMLMetaElement::SetMetaReferrer(nsIDocument* aDocument) nsresult HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { nsIDocument *document = GetUncomposedDoc(); @@ -83,7 +83,7 @@ HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aNotify); + aOldValue, aNotify); } nsresult diff --git a/dom/html/HTMLMetaElement.h b/dom/html/HTMLMetaElement.h index d3f05826d..649ea11cf 100644 --- a/dom/html/HTMLMetaElement.h +++ b/dom/html/HTMLMetaElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -33,7 +32,9 @@ public: bool aNullParent = true) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName); diff --git a/dom/html/HTMLMeterElement.cpp b/dom/html/HTMLMeterElement.cpp index dd0e21470..9c45ed769 100644 --- a/dom/html/HTMLMeterElement.cpp +++ b/dom/html/HTMLMeterElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLMeterElement.h b/dom/html/HTMLMeterElement.h index 2e870bfa3..12b725b70 100644 --- a/dom/html/HTMLMeterElement.h +++ b/dom/html/HTMLMeterElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLModElement.cpp b/dom/html/HTMLModElement.cpp index 074fa5d5b..b148ecbcc 100644 --- a/dom/html/HTMLModElement.cpp +++ b/dom/html/HTMLModElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLModElement.h b/dom/html/HTMLModElement.h index e3afe6ebc..ae9997eb0 100644 --- a/dom/html/HTMLModElement.h +++ b/dom/html/HTMLModElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLObjectElement.cpp b/dom/html/HTMLObjectElement.cpp index 65f407889..496080c11 100644 --- a/dom/html/HTMLObjectElement.cpp +++ b/dom/html/HTMLObjectElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -298,41 +297,45 @@ HTMLObjectElement::UnbindFromTree(bool aDeep, nsresult -HTMLObjectElement::SetAttr(int32_t aNameSpaceID, nsIAtom *aName, - nsIAtom *aPrefix, const nsAString &aValue, - bool aNotify) +HTMLObjectElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { - nsresult rv = nsGenericHTMLFormElement::SetAttr(aNameSpaceID, aName, aPrefix, - aValue, aNotify); + nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); NS_ENSURE_SUCCESS(rv, rv); - // if aNotify is false, we are coming from the parser or some such place; - // we'll get bound after all the attributes have been set, so we'll do the - // object load from BindToTree/DoneAddingChildren. - // Skip the LoadObject call in that case. - // We also don't want to start loading the object when we're not yet in - // a document, just in case that the caller wants to set additional - // attributes before inserting the node into the document. - if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && - aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::data) { - return LoadObject(aNotify, true); - } - - return NS_OK; + return nsGenericHTMLFormElement::AfterSetAttr(aNamespaceID, aName, aValue, + aOldValue, aNotify); } nsresult -HTMLObjectElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) +HTMLObjectElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) { - nsresult rv = nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID, - aAttribute, aNotify); + nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); NS_ENSURE_SUCCESS(rv, rv); - // See comment in SetAttr - if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && - aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::data) { - return LoadObject(aNotify, true); + return nsGenericHTMLFormElement::OnAttrSetButNotChanged(aNamespaceID, aName, + aValue, aNotify); +} + +nsresult +HTMLObjectElement::AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + bool aNotify) +{ + if (aNamespaceID == kNameSpaceID_None) { + // if aNotify is false, we are coming from the parser or some such place; + // we'll get bound after all the attributes have been set, so we'll do the + // object load from BindToTree/DoneAddingChildren. + // Skip the LoadObject call in that case. + // We also don't want to start loading the object when we're not yet in + // a document, just in case that the caller wants to set additional + // attributes before inserting the node into the document. + if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && + aName == nsGkAtoms::data) { + return LoadObject(aNotify, true); + } } return NS_OK; diff --git a/dom/html/HTMLObjectElement.h b/dom/html/HTMLObjectElement.h index 4041b78a3..6f0990918 100644 --- a/dom/html/HTMLObjectElement.h +++ b/dom/html/HTMLObjectElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -59,11 +58,6 @@ public: bool aCompileEventHandlers) override; virtual void UnbindFromTree(bool aDeep = true, bool aNullParent = true) override; - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom *aName, - nsIAtom *aPrefix, const nsAString &aValue, - bool aNotify) override; - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) override; virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override; virtual IMEState GetDesiredIMEState() override; @@ -247,6 +241,15 @@ public: return GetContentDocument(aSubjectPrincipal); } + protected: + virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; + virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) override; + private: /** * Calls LoadObject with the correct arguments to start the plugin load. @@ -271,6 +274,18 @@ private: static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData); + /** + * This function is called by AfterSetAttr and OnAttrSetButNotChanged. + * This function will be called by AfterSetAttr whether the attribute is being + * set or unset. + * + * @param aNamespaceID the namespace of the attr being set + * @param aName the localname of the attribute being set + * @param aNotify Whether we plan to notify document observers. + */ + nsresult AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + bool aNotify); + bool mIsDoneAddingChildren; }; diff --git a/dom/html/HTMLOptGroupElement.cpp b/dom/html/HTMLOptGroupElement.cpp index 8a044fbf3..ad2527dc9 100644 --- a/dom/html/HTMLOptGroupElement.cpp +++ b/dom/html/HTMLOptGroupElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -48,7 +47,7 @@ NS_IMPL_STRING_ATTR(HTMLOptGroupElement, Label, label) nsresult -HTMLOptGroupElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLOptGroupElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = false; // Do not process any DOM events if the element is disabled @@ -66,7 +65,7 @@ HTMLOptGroupElement::PreHandleEvent(EventChainPreVisitor& aVisitor) } } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } Element* @@ -102,7 +101,8 @@ HTMLOptGroupElement::RemoveChildAt(uint32_t aIndex, bool aNotify) nsresult HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled) { // All our children <option> have their :disabled state depending on our @@ -117,7 +117,7 @@ HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aNotify); + aOldValue, aNotify); } EventStates diff --git a/dom/html/HTMLOptGroupElement.h b/dom/html/HTMLOptGroupElement.h index d53a2e32b..0d647733d 100644 --- a/dom/html/HTMLOptGroupElement.h +++ b/dom/html/HTMLOptGroupElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -35,14 +34,17 @@ public: virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override; // nsIContent - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual EventStates IntrinsicState() const override; virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; virtual nsIDOMNode* AsDOMNode() override { return this; } diff --git a/dom/html/HTMLOptionElement.cpp b/dom/html/HTMLOptionElement.cpp index 7b1e3ca2d..8cb68216c 100644 --- a/dom/html/HTMLOptionElement.cpp +++ b/dom/html/HTMLOptionElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -181,7 +180,7 @@ HTMLOptionElement::GetAttributeChangeHint(const nsIAtom* aAttribute, nsresult HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) { nsresult rv = nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, @@ -244,7 +243,8 @@ HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, nsresult HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::value && Selected()) { @@ -258,7 +258,7 @@ HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, - aValue, aNotify); + aValue, aOldValue, aNotify); } NS_IMETHODIMP diff --git a/dom/html/HTMLOptionElement.h b/dom/html/HTMLOptionElement.h index e220b84df..2d647e899 100644 --- a/dom/html/HTMLOptionElement.h +++ b/dom/html/HTMLOptionElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -47,10 +46,12 @@ public: int32_t aModType) const override; virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; void SetSelectedInternal(bool aValue, bool aNotify); diff --git a/dom/html/HTMLOptionsCollection.cpp b/dom/html/HTMLOptionsCollection.cpp index 67de97fc4..cc7384a7d 100644 --- a/dom/html/HTMLOptionsCollection.cpp +++ b/dom/html/HTMLOptionsCollection.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -239,6 +238,12 @@ HTMLOptionsCollection::GetParentObject() return mSelect; } +DocGroup* +HTMLOptionsCollection::GetDocGroup() const +{ + return mSelect ? mSelect->GetDocGroup() : nullptr; +} + NS_IMETHODIMP HTMLOptionsCollection::NamedItem(const nsAString& aName, nsIDOMNode** aReturn) diff --git a/dom/html/HTMLOptionsCollection.h b/dom/html/HTMLOptionsCollection.h index 496919555..dc13eba9d 100644 --- a/dom/html/HTMLOptionsCollection.h +++ b/dom/html/HTMLOptionsCollection.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -23,6 +22,7 @@ class nsIDOMHTMLOptionElement; namespace mozilla { namespace dom { +class DocGroup; class HTMLElementOrLong; class HTMLOptionElementOrHTMLOptGroupElement; class HTMLSelectElement; @@ -62,6 +62,7 @@ public: virtual Element* GetElementAt(uint32_t aIndex) override; virtual nsINode* GetParentObject() override; + DocGroup* GetDocGroup() const; NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(HTMLOptionsCollection, nsIHTMLCollection) diff --git a/dom/html/HTMLOutputElement.cpp b/dom/html/HTMLOutputElement.cpp index 17608c94f..b27aa3f3d 100644 --- a/dom/html/HTMLOutputElement.cpp +++ b/dom/html/HTMLOutputElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLOutputElement.h b/dom/html/HTMLOutputElement.h index 588262480..7d43ba627 100644 --- a/dom/html/HTMLOutputElement.h +++ b/dom/html/HTMLOutputElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLParagraphElement.cpp b/dom/html/HTMLParagraphElement.cpp index 1157dee43..fb8e8b84f 100644 --- a/dom/html/HTMLParagraphElement.cpp +++ b/dom/html/HTMLParagraphElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLParagraphElement.h b/dom/html/HTMLParagraphElement.h index c1e231ab7..18a904463 100644 --- a/dom/html/HTMLParagraphElement.h +++ b/dom/html/HTMLParagraphElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLPictureElement.cpp b/dom/html/HTMLPictureElement.cpp index eab405ed8..da9d0c4e9 100644 --- a/dom/html/HTMLPictureElement.cpp +++ b/dom/html/HTMLPictureElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLPictureElement.h b/dom/html/HTMLPictureElement.h index 28714e02a..dce06e98a 100644 --- a/dom/html/HTMLPictureElement.h +++ b/dom/html/HTMLPictureElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLPreElement.cpp b/dom/html/HTMLPreElement.cpp index 36a1bc657..cbcc4b70c 100644 --- a/dom/html/HTMLPreElement.cpp +++ b/dom/html/HTMLPreElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLPreElement.h b/dom/html/HTMLPreElement.h index bd86dfe0d..62318ce27 100644 --- a/dom/html/HTMLPreElement.h +++ b/dom/html/HTMLPreElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLProgressElement.cpp b/dom/html/HTMLProgressElement.cpp index fc1926ee5..eb569e8bc 100644 --- a/dom/html/HTMLProgressElement.cpp +++ b/dom/html/HTMLProgressElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLProgressElement.h b/dom/html/HTMLProgressElement.h index ec10b48ab..0a97cd1b0 100644 --- a/dom/html/HTMLProgressElement.h +++ b/dom/html/HTMLProgressElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLScriptElement.cpp b/dom/html/HTMLScriptElement.cpp index 6b0b4be59..48fa96ac9 100644 --- a/dom/html/HTMLScriptElement.cpp +++ b/dom/html/HTMLScriptElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -232,13 +231,14 @@ HTMLScriptElement::SetNoModule(bool aValue, ErrorResult& aRv) nsresult HTMLScriptElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (nsGkAtoms::async == aName && kNameSpaceID_None == aNamespaceID) { mForceAsync = false; } return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, - aNotify); + aOldValue, aNotify); } NS_IMETHODIMP diff --git a/dom/html/HTMLScriptElement.h b/dom/html/HTMLScriptElement.h index ffe9d3fbd..a0c9e4725 100644 --- a/dom/html/HTMLScriptElement.h +++ b/dom/html/HTMLScriptElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -57,7 +56,9 @@ public: // Element virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; // WebIDL void SetText(const nsAString& aValue, ErrorResult& rv); diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp index e1bc0ca62..65bfa8871 100644 --- a/dom/html/HTMLSelectElement.cpp +++ b/dom/html/HTMLSelectElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -1269,12 +1268,25 @@ HTMLSelectElement::UnbindFromTree(bool aDeep, bool aNullParent) nsresult HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) { - if (aNotify && aName == nsGkAtoms::disabled && - aNameSpaceID == kNameSpaceID_None) { - mDisabledChanged = true; + if (aNameSpaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::disabled) { + if (aNotify) { + mDisabledChanged = true; + } + } else if (aName == nsGkAtoms::multiple) { + if (!aValue && aNotify && mSelectedIndex >= 0) { + // We're changing from being a multi-select to a single-select. + // Make sure we only have one option selected before we do that. + // Note that this needs to come before we really unset the attr, + // since SetOptionsSelectedByIndex does some bail-out type + // optimization for cases when the select is not multiple that + // would lead to only a single option getting deselected. + SetSelectedIndexInternal(mSelectedIndex, aNotify); + } + } } return nsGenericHTMLFormElementWithState::BeforeSetAttr(aNameSpaceID, aName, @@ -1283,7 +1295,8 @@ HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::disabled) { @@ -1293,44 +1306,18 @@ HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } else if (aName == nsGkAtoms::autocomplete) { // Clear the cached @autocomplete attribute state mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown; + } else if (aName == nsGkAtoms::multiple) { + if (!aValue && aNotify) { + // We might have become a combobox; make sure _something_ gets + // selected in that case + CheckSelectSomething(aNotify); + } } - - UpdateState(aNotify); } return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, - aValue, aNotify); -} - -nsresult -HTMLSelectElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) -{ - if (aNotify && aNameSpaceID == kNameSpaceID_None && - aAttribute == nsGkAtoms::multiple) { - // We're changing from being a multi-select to a single-select. - // Make sure we only have one option selected before we do that. - // Note that this needs to come before we really unset the attr, - // since SetOptionsSelectedByIndex does some bail-out type - // optimization for cases when the select is not multiple that - // would lead to only a single option getting deselected. - if (mSelectedIndex >= 0) { - SetSelectedIndexInternal(mSelectedIndex, aNotify); - } - } - - nsresult rv = nsGenericHTMLFormElementWithState::UnsetAttr(aNameSpaceID, aAttribute, - aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - if (aNotify && aNameSpaceID == kNameSpaceID_None && - aAttribute == nsGkAtoms::multiple) { - // We might have become a combobox; make sure _something_ gets - // selected in that case - CheckSelectSomething(aNotify); - } - - return rv; + aValue, aOldValue, + aNotify); } void @@ -1442,14 +1429,14 @@ HTMLSelectElement::IsDisabledForEvents(WidgetEvent* aEvent) } nsresult -HTMLSelectElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLSelectElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = false; if (IsDisabledForEvents(aVisitor.mEvent)) { return NS_OK; } - return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor); + return nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor); } nsresult diff --git a/dom/html/HTMLSelectElement.h b/dom/html/HTMLSelectElement.h index b9041c885..0c10f90fa 100644 --- a/dom/html/HTMLSelectElement.h +++ b/dom/html/HTMLSelectElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -278,7 +277,8 @@ public: virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; // nsIContent - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; @@ -374,12 +374,12 @@ public: bool aCompileEventHandlers) override; virtual void UnbindFromTree(bool aDeep, bool aNullParent) override; virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; virtual void DoneAddingChildren(bool aHaveNotified) override; virtual bool IsDoneAddingChildren() override { diff --git a/dom/html/HTMLShadowElement.cpp b/dom/html/HTMLShadowElement.cpp deleted file mode 100644 index 8824c2875..000000000 --- a/dom/html/HTMLShadowElement.cpp +++ /dev/null @@ -1,373 +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 "mozilla/dom/ShadowRoot.h" - -#include "ChildIterator.h" -#include "nsContentUtils.h" -#include "nsDocument.h" -#include "mozilla/dom/HTMLShadowElement.h" -#include "mozilla/dom/HTMLUnknownElement.h" -#include "mozilla/dom/HTMLShadowElementBinding.h" - -// Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Shadow) to add check for web components -// being enabled. -nsGenericHTMLElement* -NS_NewHTMLShadowElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, - mozilla::dom::FromParser aFromParser) -{ - // When this check is removed, remove the nsDocument.h and - // HTMLUnknownElement.h includes. Also remove nsINode::IsHTMLShadowElement. - // - // We have to jump through some hoops to be able to produce both NodeInfo* and - // already_AddRefed<NodeInfo>& for our callees. - RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo); - if (!nsDocument::IsWebComponentsEnabled(nodeInfo)) { - already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget()); - return new mozilla::dom::HTMLUnknownElement(nodeInfoArg); - } - - already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget()); - return new mozilla::dom::HTMLShadowElement(nodeInfoArg); -} - -using namespace mozilla::dom; - -HTMLShadowElement::HTMLShadowElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) - : nsGenericHTMLElement(aNodeInfo), mIsInsertionPoint(false) -{ -} - -HTMLShadowElement::~HTMLShadowElement() -{ - if (mProjectedShadow) { - mProjectedShadow->RemoveMutationObserver(this); - } -} - -NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLShadowElement) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLShadowElement, - nsGenericHTMLElement) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProjectedShadow) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLShadowElement, - nsGenericHTMLElement) - if (tmp->mProjectedShadow) { - tmp->mProjectedShadow->RemoveMutationObserver(tmp); - tmp->mProjectedShadow = nullptr; - } -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_ADDREF_INHERITED(HTMLShadowElement, Element) -NS_IMPL_RELEASE_INHERITED(HTMLShadowElement, Element) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLShadowElement) -NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement) - -NS_IMPL_ELEMENT_CLONE(HTMLShadowElement) - -JSObject* -HTMLShadowElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) -{ - return HTMLShadowElementBinding::Wrap(aCx, this, aGivenProto); -} - -void -HTMLShadowElement::SetProjectedShadow(ShadowRoot* aProjectedShadow) -{ - if (mProjectedShadow) { - mProjectedShadow->RemoveMutationObserver(this); - - // The currently projected ShadowRoot is going away, - // thus the destination insertion points need to be updated. - ExplicitChildIterator childIterator(mProjectedShadow); - for (nsIContent* content = childIterator.GetNextChild(); - content; - content = childIterator.GetNextChild()) { - ShadowRoot::RemoveDestInsertionPoint(this, content->DestInsertionPoints()); - } - } - - mProjectedShadow = aProjectedShadow; - if (mProjectedShadow) { - // A new ShadowRoot is being projected, thus its explcit - // children will be distributed to this shadow insertion point. - ExplicitChildIterator childIterator(mProjectedShadow); - for (nsIContent* content = childIterator.GetNextChild(); - content; - content = childIterator.GetNextChild()) { - content->DestInsertionPoints().AppendElement(this); - } - - // Watch for mutations on the projected shadow because - // it affects the nodes that are distributed to this shadow - // insertion point. - mProjectedShadow->AddMutationObserver(this); - } -} - -static bool -IsInFallbackContent(nsIContent* aContent) -{ - nsINode* parentNode = aContent->GetParentNode(); - while (parentNode) { - if (parentNode->IsHTMLElement(nsGkAtoms::content)) { - return true; - } - parentNode = parentNode->GetParentNode(); - } - - return false; -} - -nsresult -HTMLShadowElement::BindToTree(nsIDocument* aDocument, - nsIContent* aParent, - nsIContent* aBindingParent, - bool aCompileEventHandlers) -{ - RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow(); - - nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, - aBindingParent, - aCompileEventHandlers); - NS_ENSURE_SUCCESS(rv, rv); - - ShadowRoot* containingShadow = GetContainingShadow(); - if (containingShadow && !oldContainingShadow) { - // Keep track of all descendant <shadow> elements in tree order so - // that when the current shadow insertion point is removed, the next - // one can be found quickly. - TreeOrderComparator comparator; - containingShadow->ShadowDescendants().InsertElementSorted(this, comparator); - - if (containingShadow->ShadowDescendants()[0] != this) { - // Only the first <shadow> (in tree order) of a ShadowRoot can be an insertion point. - return NS_OK; - } - - if (IsInFallbackContent(this)) { - // If the first shadow element in tree order is invalid (in fallback content), - // the containing ShadowRoot will not have a shadow insertion point. - containingShadow->SetShadowElement(nullptr); - } else { - mIsInsertionPoint = true; - containingShadow->SetShadowElement(this); - } - - containingShadow->SetInsertionPointChanged(); - } - - if (mIsInsertionPoint && containingShadow) { - // Propagate BindToTree calls to projected shadow root children. - ShadowRoot* projectedShadow = containingShadow->GetOlderShadowRoot(); - if (projectedShadow) { - projectedShadow->SetIsComposedDocParticipant(IsInComposedDoc()); - - for (nsIContent* child = projectedShadow->GetFirstChild(); child; - child = child->GetNextSibling()) { - rv = child->BindToTree(nullptr, projectedShadow, - projectedShadow->GetBindingParent(), - aCompileEventHandlers); - NS_ENSURE_SUCCESS(rv, rv); - } - } - } - - return NS_OK; -} - -void -HTMLShadowElement::UnbindFromTree(bool aDeep, bool aNullParent) -{ - RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow(); - - if (mIsInsertionPoint && oldContainingShadow) { - // Propagate UnbindFromTree call to previous projected shadow - // root children. - ShadowRoot* projectedShadow = oldContainingShadow->GetOlderShadowRoot(); - if (projectedShadow) { - for (nsIContent* child = projectedShadow->GetFirstChild(); child; - child = child->GetNextSibling()) { - child->UnbindFromTree(true, false); - } - - projectedShadow->SetIsComposedDocParticipant(false); - } - } - - nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); - - if (oldContainingShadow && !GetContainingShadow() && mIsInsertionPoint) { - nsTArray<HTMLShadowElement*>& shadowDescendants = - oldContainingShadow->ShadowDescendants(); - shadowDescendants.RemoveElement(this); - oldContainingShadow->SetShadowElement(nullptr); - - // Find the next shadow insertion point. - if (shadowDescendants.Length() > 0 && - !IsInFallbackContent(shadowDescendants[0])) { - oldContainingShadow->SetShadowElement(shadowDescendants[0]); - } - - oldContainingShadow->SetInsertionPointChanged(); - - mIsInsertionPoint = false; - } -} - -void -HTMLShadowElement::DistributeSingleNode(nsIContent* aContent) -{ - if (aContent->DestInsertionPoints().Contains(this)) { - // Node has already been distrbuted this this node, - // we are done. - return; - } - - aContent->DestInsertionPoints().AppendElement(this); - - // Handle the case where the shadow element is a child of - // a node with a ShadowRoot. The nodes that have been distributed to - // this shadow insertion point will need to be reprojected into the - // insertion points of the parent's ShadowRoot. - ShadowRoot* parentShadowRoot = GetParent()->GetShadowRoot(); - if (parentShadowRoot) { - parentShadowRoot->DistributeSingleNode(aContent); - return; - } - - // Handle the case where the parent of this shadow element is a ShadowRoot - // that is projected into a shadow insertion point in the younger ShadowRoot. - ShadowRoot* containingShadow = GetContainingShadow(); - ShadowRoot* youngerShadow = containingShadow->GetYoungerShadowRoot(); - if (youngerShadow && GetParent() == containingShadow) { - HTMLShadowElement* youngerShadowElement = youngerShadow->GetShadowElement(); - if (youngerShadowElement) { - youngerShadowElement->DistributeSingleNode(aContent); - } - } -} - -void -HTMLShadowElement::RemoveDistributedNode(nsIContent* aContent) -{ - ShadowRoot::RemoveDestInsertionPoint(this, aContent->DestInsertionPoints()); - - // Handle the case where the shadow element is a child of - // a node with a ShadowRoot. The nodes that have been distributed to - // this shadow insertion point will need to be removed from the - // insertion points of the parent's ShadowRoot. - ShadowRoot* parentShadowRoot = GetParent()->GetShadowRoot(); - if (parentShadowRoot) { - parentShadowRoot->RemoveDistributedNode(aContent); - return; - } - - // Handle the case where the parent of this shadow element is a ShadowRoot - // that is projected into a shadow insertion point in the younger ShadowRoot. - ShadowRoot* containingShadow = GetContainingShadow(); - ShadowRoot* youngerShadow = containingShadow->GetYoungerShadowRoot(); - if (youngerShadow && GetParent() == containingShadow) { - HTMLShadowElement* youngerShadowElement = youngerShadow->GetShadowElement(); - if (youngerShadowElement) { - youngerShadowElement->RemoveDistributedNode(aContent); - } - } -} - -void -HTMLShadowElement::DistributeAllNodes() -{ - // All the explicit children of the projected ShadowRoot are distributed - // into this shadow insertion point so update the destination insertion - // points. - ShadowRoot* containingShadow = GetContainingShadow(); - ShadowRoot* olderShadow = containingShadow->GetOlderShadowRoot(); - if (olderShadow) { - ExplicitChildIterator childIterator(olderShadow); - for (nsIContent* content = childIterator.GetNextChild(); - content; - content = childIterator.GetNextChild()) { - ShadowRoot::RemoveDestInsertionPoint(this, content->DestInsertionPoints()); - content->DestInsertionPoints().AppendElement(this); - } - } - - // Handle the case where the shadow element is a child of - // a node with a ShadowRoot. The nodes that have been distributed to - // this shadow insertion point will need to be reprojected into the - // insertion points of the parent's ShadowRoot. - ShadowRoot* parentShadowRoot = GetParent()->GetShadowRoot(); - if (parentShadowRoot) { - parentShadowRoot->DistributeAllNodes(); - return; - } - - // Handle the case where the parent of this shadow element is a ShadowRoot - // that is projected into a shadow insertion point in the younger ShadowRoot. - ShadowRoot* youngerShadow = containingShadow->GetYoungerShadowRoot(); - if (youngerShadow && GetParent() == containingShadow) { - HTMLShadowElement* youngerShadowElement = youngerShadow->GetShadowElement(); - if (youngerShadowElement) { - youngerShadowElement->DistributeAllNodes(); - } - } -} - -void -HTMLShadowElement::ContentAppended(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aFirstNewContent, - int32_t aNewIndexInContainer) -{ - // Watch for content appended to the projected shadow (the ShadowRoot that - // will be rendered in place of this shadow insertion point) because the - // nodes may need to be distributed into other insertion points. - nsIContent* currentChild = aFirstNewContent; - while (currentChild) { - if (ShadowRoot::IsPooledNode(currentChild, aContainer, mProjectedShadow)) { - DistributeSingleNode(currentChild); - } - currentChild = currentChild->GetNextSibling(); - } -} - -void -HTMLShadowElement::ContentInserted(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild, - int32_t aIndexInContainer) -{ - // Watch for content appended to the projected shadow (the ShadowRoot that - // will be rendered in place of this shadow insertion point) because the - // nodes may need to be distributed into other insertion points. - if (!ShadowRoot::IsPooledNode(aChild, aContainer, mProjectedShadow)) { - return; - } - - DistributeSingleNode(aChild); -} - -void -HTMLShadowElement::ContentRemoved(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild, - int32_t aIndexInContainer, - nsIContent* aPreviousSibling) -{ - // Watch for content removed from the projected shadow (the ShadowRoot that - // will be rendered in place of this shadow insertion point) because the - // nodes may need to be removed from other insertion points. - if (!ShadowRoot::IsPooledNode(aChild, aContainer, mProjectedShadow)) { - return; - } - - RemoveDistributedNode(aChild); -} - diff --git a/dom/html/HTMLShadowElement.h b/dom/html/HTMLShadowElement.h deleted file mode 100644 index 95083b802..000000000 --- a/dom/html/HTMLShadowElement.h +++ /dev/null @@ -1,96 +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/. */ - -#ifndef mozilla_dom_HTMLShadowElement_h__ -#define mozilla_dom_HTMLShadowElement_h__ - -#include "nsGenericHTMLElement.h" - -namespace mozilla { -namespace dom { - -class HTMLShadowElement final : public nsGenericHTMLElement, - public nsStubMutationObserver -{ -public: - explicit HTMLShadowElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo); - - // nsISupports - NS_DECL_ISUPPORTS_INHERITED - - NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED - NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED - NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED - - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLShadowElement, - nsGenericHTMLElement) - - static HTMLShadowElement* FromContent(nsIContent* aContent) - { - if (aContent->IsHTMLShadowElement()) { - return static_cast<HTMLShadowElement*>(aContent); - } - - return nullptr; - } - - virtual bool IsHTMLShadowElement() const override { return true; } - - virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; - - virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, - nsIContent* aBindingParent, - bool aCompileEventHandlers) override; - - virtual void UnbindFromTree(bool aDeep = true, - bool aNullParent = true) override; - - bool IsInsertionPoint() { return mIsInsertionPoint; } - - /** - * Sets the ShadowRoot that will be rendered in place of - * this shadow insertion point. - */ - void SetProjectedShadow(ShadowRoot* aProjectedShadow); - - /** - * Distributes a single explicit child of the projected ShadowRoot - * to relevant insertion points. - */ - void DistributeSingleNode(nsIContent* aContent); - - /** - * Removes a single explicit child of the projected ShadowRoot - * from relevant insertion points. - */ - void RemoveDistributedNode(nsIContent* aContent); - - /** - * Distributes all the explicit children of the projected ShadowRoot - * to the shadow insertion point in the younger ShadowRoot and - * the content insertion point of the parent node's ShadowRoot. - */ - void DistributeAllNodes(); - - // WebIDL methods. - ShadowRoot* GetOlderShadowRoot() { return mProjectedShadow; } - -protected: - virtual ~HTMLShadowElement(); - - virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override; - - // The ShadowRoot that will be rendered in place of this shadow insertion point. - RefPtr<ShadowRoot> mProjectedShadow; - - bool mIsInsertionPoint; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_HTMLShadowElement_h__ - diff --git a/dom/html/HTMLSharedElement.cpp b/dom/html/HTMLSharedElement.cpp index bcb84d29b..e8c75f8aa 100644 --- a/dom/html/HTMLSharedElement.cpp +++ b/dom/html/HTMLSharedElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -231,52 +230,32 @@ SetBaseTargetUsingFirstBaseWithTarget(nsIDocument* aDocument, } nsresult -HTMLSharedElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) +HTMLSharedElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { - nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, - aValue, aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - // If the href attribute of a <base> tag is changing, we may need to update - // the document's base URI, which will cause all the links on the page to be - // re-resolved given the new base. If the target attribute is changing, we - // similarly need to change the base target. - if (mNodeInfo->Equals(nsGkAtoms::base) && - aNameSpaceID == kNameSpaceID_None && - IsInUncomposedDoc()) { - if (aName == nsGkAtoms::href) { - SetBaseURIUsingFirstBaseWithHref(GetUncomposedDoc(), this); - } else if (aName == nsGkAtoms::target) { - SetBaseTargetUsingFirstBaseWithTarget(GetUncomposedDoc(), this); - } - } - - return NS_OK; -} - -nsresult -HTMLSharedElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName, - bool aNotify) -{ - nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aName, aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - // If we're the first <base> with an href and our href attribute is being - // unset, then we're no longer the first <base> with an href, and we need to - // find the new one. Similar for target. - if (mNodeInfo->Equals(nsGkAtoms::base) && - aNameSpaceID == kNameSpaceID_None && - IsInUncomposedDoc()) { + if (aNamespaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::href) { - SetBaseURIUsingFirstBaseWithHref(GetUncomposedDoc(), nullptr); + // If the href attribute of a <base> tag is changing, we may need to + // update the document's base URI, which will cause all the links on the + // page to be re-resolved given the new base. + // If the href is being unset (aValue is null), we will need to find a new + // <base>. + if (mNodeInfo->Equals(nsGkAtoms::base) && IsInUncomposedDoc()) { + SetBaseURIUsingFirstBaseWithHref(GetUncomposedDoc(), + aValue ? this : nullptr); + } } else if (aName == nsGkAtoms::target) { - SetBaseTargetUsingFirstBaseWithTarget(GetUncomposedDoc(), nullptr); + // The target attribute is in pretty much the same situation as the href + // attribute, above. + if (mNodeInfo->Equals(nsGkAtoms::base) && IsInUncomposedDoc()) { + SetBaseTargetUsingFirstBaseWithTarget(GetUncomposedDoc(), + aValue ? this : nullptr); + } } } - - return NS_OK; + return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, + aOldValue, aNotify); } nsresult diff --git a/dom/html/HTMLSharedElement.h b/dom/html/HTMLSharedElement.h index 205750cf6..c0f8618dc 100644 --- a/dom/html/HTMLSharedElement.h +++ b/dom/html/HTMLSharedElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -59,17 +58,6 @@ public: nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult) override; - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName, - bool aNotify) override; virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, @@ -181,6 +169,11 @@ protected: virtual ~HTMLSharedElement(); virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; + + virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; }; } // namespace dom diff --git a/dom/html/HTMLSharedListElement.cpp b/dom/html/HTMLSharedListElement.cpp index a76a7513c..08ccdbf9a 100644 --- a/dom/html/HTMLSharedListElement.cpp +++ b/dom/html/HTMLSharedListElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLSharedListElement.h b/dom/html/HTMLSharedListElement.h index 2f733aa2e..3ff6e0430 100644 --- a/dom/html/HTMLSharedListElement.h +++ b/dom/html/HTMLSharedListElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLSharedObjectElement.cpp b/dom/html/HTMLSharedObjectElement.cpp index 889fd5aef..f8b795af7 100644 --- a/dom/html/HTMLSharedObjectElement.cpp +++ b/dom/html/HTMLSharedObjectElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -161,27 +160,53 @@ HTMLSharedObjectElement::UnbindFromTree(bool aDeep, nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); } +nsresult +HTMLSharedObjectElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) +{ + if (aValue) { + nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); + NS_ENSURE_SUCCESS(rv, rv); + } + + return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, + aOldValue, aNotify); +} nsresult -HTMLSharedObjectElement::SetAttr(int32_t aNameSpaceID, nsIAtom *aName, - nsIAtom *aPrefix, const nsAString &aValue, - bool aNotify) +HTMLSharedObjectElement::OnAttrSetButNotChanged(int32_t aNamespaceID, + nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) { - nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, - aValue, aNotify); + nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); NS_ENSURE_SUCCESS(rv, rv); - // if aNotify is false, we are coming from the parser or some such place; - // we'll get bound after all the attributes have been set, so we'll do the - // object load from BindToTree/DoneAddingChildren. - // Skip the LoadObject call in that case. - // We also don't want to start loading the object when we're not yet in - // a document, just in case that the caller wants to set additional - // attributes before inserting the node into the document. - if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren && - aNameSpaceID == kNameSpaceID_None && aName == URIAttrName() - && !BlockEmbedContentLoading()) { - return LoadObject(aNotify, true); + return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName, + aValue, aNotify); +} + +nsresult +HTMLSharedObjectElement::AfterMaybeChangeAttr(int32_t aNamespaceID, + nsIAtom* aName, + bool aNotify) +{ + if (aNamespaceID == kNameSpaceID_None) { + if (aName == URIAttrName()) { + // If aNotify is false, we are coming from the parser or some such place; + // we'll get bound after all the attributes have been set, so we'll do the + // object load from BindToTree/DoneAddingChildren. + // Skip the LoadObject call in that case. + // We also don't want to start loading the object when we're not yet in + // a document, just in case that the caller wants to set additional + // attributes before inserting the node into the document. + if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren) { + nsresult rv = LoadObject(aNotify, true); + NS_ENSURE_SUCCESS(rv, rv); + } + } } return NS_OK; diff --git a/dom/html/HTMLSharedObjectElement.h b/dom/html/HTMLSharedObjectElement.h index c70ba8ebd..e550b9927 100644 --- a/dom/html/HTMLSharedObjectElement.h +++ b/dom/html/HTMLSharedObjectElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -57,9 +56,6 @@ public: bool aCompileEventHandlers) override; virtual void UnbindFromTree(bool aDeep = true, bool aNullParent = true) override; - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom *aName, - nsIAtom *aPrefix, const nsAString &aValue, - bool aNotify) override; virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override; virtual IMEState GetDesiredIMEState() override; @@ -200,6 +196,16 @@ public: * Calls LoadObject with the correct arguments to start the plugin load. */ void StartObjectLoad(bool aNotify, bool aForceLoad); + +protected: + virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; + virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) override; + private: virtual ~HTMLSharedObjectElement(); @@ -222,6 +228,17 @@ private: nsRuleData* aData); /** + * This function is called by AfterSetAttr and OnAttrSetButNotChanged. + * It will not be called if the value is being unset. + * + * @param aNamespaceID the namespace of the attr being set + * @param aName the localname of the attribute being set + * @param aNotify Whether we plan to notify document observers. + */ + nsresult AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + bool aNotify); + + /** * Decides whether we should load embed node content. * * If this is an embed node there are cases in which we should not try to load diff --git a/dom/html/HTMLSlotElement.cpp b/dom/html/HTMLSlotElement.cpp new file mode 100644 index 000000000..e2dc3d8ff --- /dev/null +++ b/dom/html/HTMLSlotElement.cpp @@ -0,0 +1,245 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "mozilla/dom/DocGroup.h" +#include "mozilla/dom/HTMLSlotElement.h" +#include "mozilla/dom/HTMLSlotElementBinding.h" +#include "mozilla/dom/HTMLUnknownElement.h" +#include "mozilla/dom/ShadowRoot.h" +#include "nsGkAtoms.h" +#include "nsDocument.h" + +nsGenericHTMLElement* +NS_NewHTMLSlotElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, + mozilla::dom::FromParser aFromParser) +{ + RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo); + if (nsDocument::IsWebComponentsEnabled(nodeInfo->GetDocument())) { + already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget()); + return new mozilla::dom::HTMLSlotElement(nodeInfoArg); + } + + already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget()); + return new mozilla::dom::HTMLUnknownElement(nodeInfoArg); +} + +namespace mozilla { +namespace dom { + +HTMLSlotElement::HTMLSlotElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) + : nsGenericHTMLElement(aNodeInfo) +{ +} + +HTMLSlotElement::~HTMLSlotElement() +{ +} + +NS_IMPL_ADDREF_INHERITED(HTMLSlotElement, nsGenericHTMLElement) +NS_IMPL_RELEASE_INHERITED(HTMLSlotElement, nsGenericHTMLElement) + +NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLSlotElement, + nsGenericHTMLElement, + mAssignedNodes) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HTMLSlotElement) +NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement) + +NS_IMPL_ELEMENT_CLONE(HTMLSlotElement) + +nsresult +HTMLSlotElement::BindToTree(nsIDocument* aDocument, + nsIContent* aParent, + nsIContent* aBindingParent, + bool aCompileEventHandlers) +{ + RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow(); + + nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, + aBindingParent, + aCompileEventHandlers); + NS_ENSURE_SUCCESS(rv, rv); + + ShadowRoot* containingShadow = GetContainingShadow(); + if (containingShadow && !oldContainingShadow) { + containingShadow->AddSlot(this); + } + + return NS_OK; +} + +void +HTMLSlotElement::UnbindFromTree(bool aDeep, bool aNullParent) +{ + RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow(); + + nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); + + if (oldContainingShadow && !GetContainingShadow()) { + oldContainingShadow->RemoveSlot(this); + } +} + +nsresult +HTMLSlotElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) +{ + if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::name) { + if (ShadowRoot* containingShadow = GetContainingShadow()) { + containingShadow->RemoveSlot(this); + } + } + + return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName, aValue, + aNotify); +} + +nsresult +HTMLSlotElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) +{ + + if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::name) { + if (ShadowRoot* containingShadow = GetContainingShadow()) { + containingShadow->AddSlot(this); + } + } + + return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, + aOldValue, aNotify); +} + +/** + * Flatten assigned nodes given a slot, as in: + * https://dom.spec.whatwg.org/#find-flattened-slotables + */ +static void +FlattenAssignedNodes(HTMLSlotElement* aSlot, nsTArray<RefPtr<nsINode>>& aNodes) +{ + if (!aSlot->GetContainingShadow()) { + return; + } + + const nsTArray<RefPtr<nsINode>>& assignedNodes = aSlot->AssignedNodes(); + + // If assignedNodes is empty, use children of slot as fallback content. + if (assignedNodes.IsEmpty()) { + for (nsIContent* child = aSlot->AsContent()->GetFirstChild(); + child; + child = child->GetNextSibling()) { + if (!child->IsSlotable()) { + continue; + } + + if (child->IsHTMLElement(nsGkAtoms::slot)) { + FlattenAssignedNodes(HTMLSlotElement::FromContent(child), aNodes); + } else { + aNodes.AppendElement(child); + } + } + return; + } + + for (uint32_t i = 0; i < assignedNodes.Length(); i++) { + nsINode* assignedNode = assignedNodes[i]; + if (assignedNode->IsHTMLElement(nsGkAtoms::slot)) { + FlattenAssignedNodes( + HTMLSlotElement::FromContent(assignedNode->AsContent()), aNodes); + } else { + aNodes.AppendElement(assignedNode); + } + } +} + +void +HTMLSlotElement::AssignedNodes(const AssignedNodesOptions& aOptions, + nsTArray<RefPtr<nsINode>>& aNodes) +{ + if (aOptions.mFlatten) { + return FlattenAssignedNodes(this, aNodes); + } + + aNodes = mAssignedNodes; +} + +void HTMLSlotElement::AssignedElements(const AssignedNodesOptions& aOptions, + nsTArray<RefPtr<Element>>& aElements) { + AutoTArray<RefPtr<nsINode>, 128> assignedNodes; + AssignedNodes(aOptions, assignedNodes); + for (const RefPtr<nsINode>& assignedNode : assignedNodes) { + if (assignedNode->IsElement()) { + aElements.AppendElement(assignedNode->AsElement()); + } + } +} + +const nsTArray<RefPtr<nsINode>>& +HTMLSlotElement::AssignedNodes() const +{ + return mAssignedNodes; +} + +void +HTMLSlotElement::InsertAssignedNode(uint32_t aIndex, nsINode* aNode) +{ + mAssignedNodes.InsertElementAt(aIndex, aNode); + aNode->AsContent()->SetAssignedSlot(this); +} + +void +HTMLSlotElement::AppendAssignedNode(nsINode* aNode) +{ + mAssignedNodes.AppendElement(aNode); + aNode->AsContent()->SetAssignedSlot(this); +} + +void +HTMLSlotElement::RemoveAssignedNode(nsINode* aNode) +{ + mAssignedNodes.RemoveElement(aNode); + aNode->AsContent()->SetAssignedSlot(nullptr); +} + +void +HTMLSlotElement::ClearAssignedNodes() +{ + for (uint32_t i = 0; i < mAssignedNodes.Length(); i++) { + mAssignedNodes[i]->AsContent()->SetAssignedSlot(nullptr); + } + + mAssignedNodes.Clear(); +} + +void +HTMLSlotElement::EnqueueSlotChangeEvent() const +{ + DocGroup* docGroup = OwnerDoc()->GetDocGroup(); + if (!docGroup) { + return; + } + + docGroup->SignalSlotChange(this); +} + +void +HTMLSlotElement::FireSlotChangeEvent() +{ + nsContentUtils::DispatchTrustedEvent(OwnerDoc(), + static_cast<nsIContent*>(this), + NS_LITERAL_STRING("slotchange"), true, + false); +} + +JSObject* +HTMLSlotElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) +{ + return HTMLSlotElementBinding::Wrap(aCx, this, aGivenProto); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/html/HTMLSlotElement.h b/dom/html/HTMLSlotElement.h new file mode 100644 index 000000000..f20e6dc7f --- /dev/null +++ b/dom/html/HTMLSlotElement.h @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#ifndef mozilla_dom_HTMLSlotElement_h +#define mozilla_dom_HTMLSlotElement_h + +#include "nsIDOMHTMLElement.h" +#include "nsGenericHTMLElement.h" +#include "nsTArray.h" + +namespace mozilla { +namespace dom { + +struct AssignedNodesOptions; + +class HTMLSlotElement final : public nsGenericHTMLElement +{ +public: + explicit HTMLSlotElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo); + NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLSlotElement, slot) + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLSlotElement, nsGenericHTMLElement) + virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override; + + // nsIContent + virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, + nsIContent* aBindingParent, + bool aCompileEventHandlers) override; + virtual void UnbindFromTree(bool aDeep = true, + bool aNullParent = true) override; + + virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) override; + virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; + + // WebIDL + void SetName(const nsAString& aName, ErrorResult& aRv) + { + SetHTMLAttr(nsGkAtoms::name, aName, aRv); + } + + void GetName(nsAString& aName) + { + GetHTMLAttr(nsGkAtoms::name, aName); + } + + void AssignedNodes(const AssignedNodesOptions& aOptions, + nsTArray<RefPtr<nsINode>>& aNodes); + + void AssignedElements(const AssignedNodesOptions& aOptions, + nsTArray<RefPtr<Element>>& aNodes); + + // Helper methods + const nsTArray<RefPtr<nsINode>>& AssignedNodes() const; + void InsertAssignedNode(uint32_t aIndex, nsINode* aNode); + void AppendAssignedNode(nsINode* aNode); + void RemoveAssignedNode(nsINode* aNode); + void ClearAssignedNodes(); + + void EnqueueSlotChangeEvent() const; + void FireSlotChangeEvent(); + +protected: + virtual ~HTMLSlotElement(); + virtual JSObject* + WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; + + nsTArray<RefPtr<nsINode>> mAssignedNodes; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_HTMLSlotElement_h diff --git a/dom/html/HTMLSourceElement.cpp b/dom/html/HTMLSourceElement.cpp index 73d9c9d8c..4d202885c 100644 --- a/dom/html/HTMLSourceElement.cpp +++ b/dom/html/HTMLSourceElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -98,7 +97,8 @@ HTMLSourceElement::UpdateMediaList(const nsAttrValue* aValue) nsresult HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { // If we are associated with a <picture> with a valid <img>, notify it of // responsive parameter changes @@ -143,7 +143,7 @@ HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, - aValue, aNotify); + aValue, aOldValue, aNotify); } nsresult diff --git a/dom/html/HTMLSourceElement.h b/dom/html/HTMLSourceElement.h index 595e21015..b7942e711 100644 --- a/dom/html/HTMLSourceElement.h +++ b/dom/html/HTMLSourceElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -110,6 +109,7 @@ protected: protected: virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) override; private: diff --git a/dom/html/HTMLSpanElement.cpp b/dom/html/HTMLSpanElement.cpp index d1888f8bd..9ac1b76f0 100644 --- a/dom/html/HTMLSpanElement.cpp +++ b/dom/html/HTMLSpanElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLSpanElement.h b/dom/html/HTMLSpanElement.h index e76bc8781..489bedf83 100644 --- a/dom/html/HTMLSpanElement.h +++ b/dom/html/HTMLSpanElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLStyleElement.cpp b/dom/html/HTMLStyleElement.cpp index 87dc68f83..864488f03 100644 --- a/dom/html/HTMLStyleElement.cpp +++ b/dom/html/HTMLStyleElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -171,7 +170,8 @@ HTMLStyleElement::UnbindFromTree(bool aDeep, bool aNullParent) nsresult HTMLStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::title || @@ -185,7 +185,7 @@ HTMLStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aNotify); + aOldValue, aNotify); } NS_IMETHODIMP diff --git a/dom/html/HTMLStyleElement.h b/dom/html/HTMLStyleElement.h index 9f82b8e51..60331dc5d 100644 --- a/dom/html/HTMLStyleElement.h +++ b/dom/html/HTMLStyleElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -48,6 +47,7 @@ public: bool aNullParent = true) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) override; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; diff --git a/dom/html/HTMLSummaryElement.cpp b/dom/html/HTMLSummaryElement.cpp index ee3c07b20..42ead6b87 100644 --- a/dom/html/HTMLSummaryElement.cpp +++ b/dom/html/HTMLSummaryElement.cpp @@ -14,17 +14,7 @@ #include "mozilla/TextEvents.h" #include "nsFocusManager.h" -// Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Summary) to add pref check. -nsGenericHTMLElement* -NS_NewHTMLSummaryElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, - mozilla::dom::FromParser aFromParser) -{ - if (!mozilla::dom::HTMLDetailsElement::IsDetailsEnabled()) { - return new mozilla::dom::HTMLUnknownElement(aNodeInfo); - } - - return new mozilla::dom::HTMLSummaryElement(aNodeInfo); -} +NS_IMPL_NS_NEW_HTML_ELEMENT(Summary) namespace mozilla { namespace dom { diff --git a/dom/html/HTMLTableCaptionElement.cpp b/dom/html/HTMLTableCaptionElement.cpp index fd9328de8..173507fb7 100644 --- a/dom/html/HTMLTableCaptionElement.cpp +++ b/dom/html/HTMLTableCaptionElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTableCaptionElement.h b/dom/html/HTMLTableCaptionElement.h index 1c84118d7..efe5fa1ff 100644 --- a/dom/html/HTMLTableCaptionElement.h +++ b/dom/html/HTMLTableCaptionElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTableCellElement.cpp b/dom/html/HTMLTableCellElement.cpp index 1cf413413..2c795d2d4 100644 --- a/dom/html/HTMLTableCellElement.cpp +++ b/dom/html/HTMLTableCellElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -107,9 +106,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 +114,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 ab7a918eb..10af61fc2 100644 --- a/dom/html/HTMLTableCellElement.h +++ b/dom/html/HTMLTableCellElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -148,6 +147,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/HTMLTableColElement.cpp b/dom/html/HTMLTableColElement.cpp index 484070bf0..0e587d760 100644 --- a/dom/html/HTMLTableColElement.cpp +++ b/dom/html/HTMLTableColElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTableColElement.h b/dom/html/HTMLTableColElement.h index 8bdc7634e..7f627deaa 100644 --- a/dom/html/HTMLTableColElement.h +++ b/dom/html/HTMLTableColElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTableElement.cpp b/dom/html/HTMLTableElement.cpp index c5b7696cf..c33d8de77 100644 --- a/dom/html/HTMLTableElement.cpp +++ b/dom/html/HTMLTableElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -322,7 +321,7 @@ TableRowsCollection::ParentDestroyed() HTMLTableElement::HTMLTableElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) : nsGenericHTMLElement(aNodeInfo), - mTableInheritedAttributes(TABLE_ATTRS_DIRTY) + mTableInheritedAttributes(nullptr) { SetHasWeirdParserInsertionMode(); } @@ -912,20 +911,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; @@ -938,7 +932,9 @@ HTMLTableElement::BuildInheritedAttributes() if (modifiableMapped) { nsAttrValue val(*value); - modifiableMapped->SetAndTakeAttr(nsGkAtoms::cellpadding, val); + bool oldValueSet; + modifiableMapped->SetAndSwapAttr(nsGkAtoms::cellpadding, val, + &oldValueSet); } newAttrs = sheet->UniqueMappedAttributes(modifiableMapped); NS_ASSERTION(newAttrs, "out of memory, but handling gracefully"); @@ -960,10 +956,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 +965,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 @@ -986,7 +982,7 @@ HTMLTableElement::UnbindFromTree(bool aDeep, bool aNullParent) nsresult HTMLTableElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) { if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) { @@ -999,13 +995,13 @@ HTMLTableElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult HTMLTableElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - bool aNotify) + const nsAttrValue* aOldValue, bool aNotify) { if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) { BuildInheritedAttributes(); } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aNotify); + aOldValue, aNotify); } } // namespace dom diff --git a/dom/html/HTMLTableElement.h b/dom/html/HTMLTableElement.h index 4e172964b..00faab0ec 100644 --- a/dom/html/HTMLTableElement.h +++ b/dom/html/HTMLTableElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -14,8 +13,6 @@ namespace mozilla { namespace dom { -#define TABLE_ATTRS_DIRTY ((nsMappedAttributes*)0x1) - class TableRowsCollection; class HTMLTableElement final : public nsGenericHTMLElement @@ -190,13 +187,15 @@ public: * Called when an attribute is about to be changed */ virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) override; /** * Called when an attribute has just been changed */ virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTableElement, nsGenericHTMLElement) @@ -220,8 +219,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/HTMLTableRowElement.cpp b/dom/html/HTMLTableRowElement.cpp index ac2463400..8f6316dc2 100644 --- a/dom/html/HTMLTableRowElement.cpp +++ b/dom/html/HTMLTableRowElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTableRowElement.h b/dom/html/HTMLTableRowElement.h index 56310e389..02ade8f66 100644 --- a/dom/html/HTMLTableRowElement.h +++ b/dom/html/HTMLTableRowElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTableSectionElement.cpp b/dom/html/HTMLTableSectionElement.cpp index e99597636..88cb76e14 100644 --- a/dom/html/HTMLTableSectionElement.cpp +++ b/dom/html/HTMLTableSectionElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTableSectionElement.h b/dom/html/HTMLTableSectionElement.h index cabde0042..638579872 100644 --- a/dom/html/HTMLTableSectionElement.h +++ b/dom/html/HTMLTableSectionElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTemplateElement.cpp b/dom/html/HTMLTemplateElement.cpp index 27fb12870..d47235347 100644 --- a/dom/html/HTMLTemplateElement.cpp +++ b/dom/html/HTMLTemplateElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTemplateElement.h b/dom/html/HTMLTemplateElement.h index 53c05c09a..af3172408 100644 --- a/dom/html/HTMLTemplateElement.h +++ b/dom/html/HTMLTemplateElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTextAreaElement.cpp b/dom/html/HTMLTextAreaElement.cpp index 4c40c16f3..0514a2660 100644 --- a/dom/html/HTMLTextAreaElement.cpp +++ b/dom/html/HTMLTextAreaElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -506,7 +505,7 @@ HTMLTextAreaElement::IsDisabledForEvents(WidgetEvent* aEvent) } nsresult -HTMLTextAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLTextAreaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = false; if (IsDisabledForEvents(aVisitor.mEvent)) { @@ -534,11 +533,22 @@ HTMLTextAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor) aVisitor.mEvent->mFlags.mNoContentDispatch = false; } - // Fire onchange (if necessary), before we do the blur, bug 370521. if (aVisitor.mEvent->mMessage == eBlur) { - FireChangeEventIfNeeded(); + // Set mWantsPreHandleEvent and fire change event in PreHandleEvent to + // prevent it breaks event target chain creation. + aVisitor.mWantsPreHandleEvent = true; } + return nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor); +} + +nsresult +HTMLTextAreaElement::PreHandleEvent(EventChainVisitor& aVisitor) +{ + if (aVisitor.mEvent->mMessage == eBlur) { + // Fire onchange (if necessary), before we do the blur, bug 370521. + FireChangeEventIfNeeded(); + } return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor); } @@ -1275,7 +1285,7 @@ HTMLTextAreaElement::UnbindFromTree(bool aDeep, bool aNullParent) nsresult HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) { if (aNotify && aName == nsGkAtoms::disabled && @@ -1337,7 +1347,8 @@ HTMLTextAreaElement::ContentChanged(nsIContent* aContent) nsresult HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled || @@ -1353,12 +1364,10 @@ HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } else if (aName == nsGkAtoms::minlength) { UpdateTooShortValidityState(); } - - UpdateState(aNotify); } return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue, - aNotify); + aOldValue, aNotify); } nsresult diff --git a/dom/html/HTMLTextAreaElement.h b/dom/html/HTMLTextAreaElement.h index 90fb680c5..f388bfa61 100644 --- a/dom/html/HTMLTextAreaElement.h +++ b/dom/html/HTMLTextAreaElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -125,7 +124,9 @@ public: int32_t aModType) const override; NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override; - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; + virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; @@ -142,7 +143,7 @@ public: * Called when an attribute is about to be changed */ virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) override; // nsIMutationObserver @@ -355,7 +356,9 @@ protected: void ContentChanged(nsIContent* aContent); virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom *aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; /** * Return if an element should have a specific validity UI diff --git a/dom/html/HTMLTimeElement.cpp b/dom/html/HTMLTimeElement.cpp index cf803eced..1772282dc 100644 --- a/dom/html/HTMLTimeElement.cpp +++ b/dom/html/HTMLTimeElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTimeElement.h b/dom/html/HTMLTimeElement.h index 2755e2c92..dbda58778 100644 --- a/dom/html/HTMLTimeElement.h +++ b/dom/html/HTMLTimeElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTitleElement.cpp b/dom/html/HTMLTitleElement.cpp index b005d104a..be0cc7bc2 100644 --- a/dom/html/HTMLTitleElement.cpp +++ b/dom/html/HTMLTitleElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTitleElement.h b/dom/html/HTMLTitleElement.h index 430ae0c1a..ea0608c75 100644 --- a/dom/html/HTMLTitleElement.h +++ b/dom/html/HTMLTitleElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTrackElement.cpp b/dom/html/HTMLTrackElement.cpp index 59810a444..07fbe2073 100644 --- a/dom/html/HTMLTrackElement.cpp +++ b/dom/html/HTMLTrackElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLTrackElement.h b/dom/html/HTMLTrackElement.h index 566f1e0d3..84828e4a9 100644 --- a/dom/html/HTMLTrackElement.h +++ b/dom/html/HTMLTrackElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLUnknownElement.cpp b/dom/html/HTMLUnknownElement.cpp index 1e01d2ce2..04555a9cb 100644 --- a/dom/html/HTMLUnknownElement.cpp +++ b/dom/html/HTMLUnknownElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLUnknownElement.h b/dom/html/HTMLUnknownElement.h index c77fba919..b9e45f83e 100644 --- a/dom/html/HTMLUnknownElement.h +++ b/dom/html/HTMLUnknownElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -7,6 +6,7 @@ #define mozilla_dom_HTMLUnknownElement_h #include "mozilla/Attributes.h" +#include "mozilla/EventStates.h" #include "nsGenericHTMLElement.h" namespace mozilla { @@ -27,7 +27,7 @@ public: : nsGenericHTMLElement(aNodeInfo) { if (NodeInfo()->Equals(nsGkAtoms::bdi)) { - SetHasDirAuto(); + AddStatesSilently(NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO); } } diff --git a/dom/html/HTMLVideoElement.cpp b/dom/html/HTMLVideoElement.cpp index bddec24c9..6cda72cfa 100644 --- a/dom/html/HTMLVideoElement.cpp +++ b/dom/html/HTMLVideoElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/HTMLVideoElement.h b/dom/html/HTMLVideoElement.h index 72e629a94..4c20faf95 100644 --- a/dom/html/HTMLVideoElement.h +++ b/dom/html/HTMLVideoElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/ImageDocument.cpp b/dom/html/ImageDocument.cpp index 451d989c3..87bf3ee99 100644 --- a/dom/html/ImageDocument.cpp +++ b/dom/html/ImageDocument.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/ImageDocument.h b/dom/html/ImageDocument.h index 945317314..75daa5f0c 100644 --- a/dom/html/ImageDocument.h +++ b/dom/html/ImageDocument.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/MediaDocument.cpp b/dom/html/MediaDocument.cpp index d74d72111..3d57d6d14 100644 --- a/dom/html/MediaDocument.cpp +++ b/dom/html/MediaDocument.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/MediaDocument.h b/dom/html/MediaDocument.h index 7d1be6265..b02fd66ad 100644 --- a/dom/html/MediaDocument.h +++ b/dom/html/MediaDocument.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/MediaError.cpp b/dom/html/MediaError.cpp index 83b9ffc5f..4b43c321e 100644 --- a/dom/html/MediaError.cpp +++ b/dom/html/MediaError.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/MediaError.h b/dom/html/MediaError.h index 27be1050e..fde662042 100644 --- a/dom/html/MediaError.h +++ b/dom/html/MediaError.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/PluginDocument.cpp b/dom/html/PluginDocument.cpp index f6be8a915..b22868062 100644 --- a/dom/html/PluginDocument.cpp +++ b/dom/html/PluginDocument.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/RadioNodeList.cpp b/dom/html/RadioNodeList.cpp index 79780e11c..752b4487b 100644 --- a/dom/html/RadioNodeList.cpp +++ b/dom/html/RadioNodeList.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/RadioNodeList.h b/dom/html/RadioNodeList.h index 8ff487feb..dff90f82e 100644 --- a/dom/html/RadioNodeList.h +++ b/dom/html/RadioNodeList.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/TextTrackManager.cpp b/dom/html/TextTrackManager.cpp index 7f9d32794..34307e47e 100644 --- a/dom/html/TextTrackManager.cpp +++ b/dom/html/TextTrackManager.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/TextTrackManager.h b/dom/html/TextTrackManager.h index 2375aa4bb..994bea38b 100644 --- a/dom/html/TextTrackManager.h +++ b/dom/html/TextTrackManager.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/TimeRanges.cpp b/dom/html/TimeRanges.cpp index debb81a2f..e808e6638 100644 --- a/dom/html/TimeRanges.cpp +++ b/dom/html/TimeRanges.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/TimeRanges.h b/dom/html/TimeRanges.h index 1811346fa..526beb0f7 100644 --- a/dom/html/TimeRanges.h +++ b/dom/html/TimeRanges.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/ValidityState.cpp b/dom/html/ValidityState.cpp index b23eb6daa..195d8aa27 100644 --- a/dom/html/ValidityState.cpp +++ b/dom/html/ValidityState.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/ValidityState.h b/dom/html/ValidityState.h index adbd86c1d..f1db3ddf6 100644 --- a/dom/html/ValidityState.h +++ b/dom/html/ValidityState.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/VideoDocument.cpp b/dom/html/VideoDocument.cpp index 76b2e326f..983baf35c 100644 --- a/dom/html/VideoDocument.cpp +++ b/dom/html/VideoDocument.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/moz.build b/dom/html/moz.build index 82d6e07b3..9cf22144a 100644 --- a/dom/html/moz.build +++ b/dom/html/moz.build @@ -1,5 +1,4 @@ # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: # 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/. @@ -52,7 +51,6 @@ EXPORTS.mozilla.dom += [ 'HTMLBRElement.h', 'HTMLButtonElement.h', 'HTMLCanvasElement.h', - 'HTMLContentElement.h', 'HTMLDataElement.h', 'HTMLDataListElement.h', 'HTMLDetailsElement.h', @@ -92,10 +90,10 @@ EXPORTS.mozilla.dom += [ 'HTMLProgressElement.h', 'HTMLScriptElement.h', 'HTMLSelectElement.h', - 'HTMLShadowElement.h', 'HTMLSharedElement.h', 'HTMLSharedListElement.h', 'HTMLSharedObjectElement.h', + 'HTMLSlotElement.h', 'HTMLSourceElement.h', 'HTMLSpanElement.h', 'HTMLStyleElement.h', @@ -131,7 +129,6 @@ SOURCES += [ 'HTMLBRElement.cpp', 'HTMLButtonElement.cpp', 'HTMLCanvasElement.cpp', - 'HTMLContentElement.cpp', 'HTMLDataElement.cpp', 'HTMLDataListElement.cpp', 'HTMLDetailsElement.cpp', @@ -172,10 +169,10 @@ SOURCES += [ 'HTMLProgressElement.cpp', 'HTMLScriptElement.cpp', 'HTMLSelectElement.cpp', - 'HTMLShadowElement.cpp', 'HTMLSharedElement.cpp', 'HTMLSharedListElement.cpp', 'HTMLSharedObjectElement.cpp', + 'HTMLSlotElement.cpp', 'HTMLSourceElement.cpp', 'HTMLSpanElement.cpp', 'HTMLStyleElement.cpp', diff --git a/dom/html/nsBrowserElement.cpp b/dom/html/nsBrowserElement.cpp index 1c2f00c15..5b9100fa1 100644 --- a/dom/html/nsBrowserElement.cpp +++ b/dom/html/nsBrowserElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsBrowserElement.h b/dom/html/nsBrowserElement.h index e0f4ca186..9a4c47d28 100644 --- a/dom/html/nsBrowserElement.h +++ b/dom/html/nsBrowserElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsDOMStringMap.cpp b/dom/html/nsDOMStringMap.cpp index 6d2bc424d..e2f0b5477 100644 --- a/dom/html/nsDOMStringMap.cpp +++ b/dom/html/nsDOMStringMap.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -62,6 +61,12 @@ nsDOMStringMap::~nsDOMStringMap() } } +DocGroup* +nsDOMStringMap::GetDocGroup() const +{ + return mElement ? mElement->GetDocGroup() : nullptr; +} + /* virtual */ JSObject* nsDOMStringMap::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) diff --git a/dom/html/nsDOMStringMap.h b/dom/html/nsDOMStringMap.h index bf28957f7..33d8d8b24 100644 --- a/dom/html/nsDOMStringMap.h +++ b/dom/html/nsDOMStringMap.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -16,6 +15,9 @@ namespace mozilla { class ErrorResult; +namespace dom { +class DocGroup; +} // namespace dom } // namespace mozilla class nsDOMStringMap : public nsStubMutationObserver, @@ -32,6 +34,8 @@ public: return mElement; } + mozilla::dom::DocGroup* GetDocGroup() const; + explicit nsDOMStringMap(mozilla::dom::Element* aElement); // WebIDL API diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index ddb476cf4..0f32d8fb4 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -497,7 +496,7 @@ nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, // We need to consider a labels element is moved to another subtree // with different root, it needs to update labels list and its root // as well. - nsDOMSlots* slots = GetExistingDOMSlots(); + nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots(); if (slots && slots->mLabelsList) { slots->mLabelsList->MaybeResetRoot(SubtreeRoot()); } @@ -524,7 +523,7 @@ nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent) // We need to consider a labels element is removed from tree, // it needs to update labels list and its root as well. - nsDOMSlots* slots = GetExistingDOMSlots(); + nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots(); if (slots && slots->mLabelsList) { slots->mLabelsList->MaybeResetRoot(SubtreeRoot()); } @@ -607,16 +606,16 @@ nsGenericHTMLElement::CheckHandleEventForAnchorsPreconditions( } nsresult -nsGenericHTMLElement::PreHandleEventForAnchors(EventChainPreVisitor& aVisitor) +nsGenericHTMLElement::GetEventTargetParentForAnchors(EventChainPreVisitor& aVisitor) { - nsresult rv = nsGenericHTMLElementBase::PreHandleEvent(aVisitor); + nsresult rv = nsGenericHTMLElementBase::GetEventTargetParent(aVisitor); NS_ENSURE_SUCCESS(rv, rv); if (!CheckHandleEventForAnchorsPreconditions(aVisitor)) { return NS_OK; } - return PreHandleEventForLinks(aVisitor); + return GetEventTargetParentForLinks(aVisitor); } nsresult @@ -655,8 +654,46 @@ nsGenericHTMLElement::GetHrefURIForAnchors() const } nsresult +nsGenericHTMLElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) +{ + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::accesskey) { + // Have to unregister before clearing flag. See UnregAccessKey + UnregAccessKey(); + if (!aValue) { + UnsetFlags(NODE_HAS_ACCESSKEY); + } + } else if (aName == nsGkAtoms::name) { + // Have to do this before clearing flag. See RemoveFromNameTable + RemoveFromNameTable(); + if (!aValue || aValue->IsEmpty()) { + ClearHasName(); + } + } else if (aName == nsGkAtoms::contenteditable) { + if (aValue) { + // Set this before the attribute is set so that any subclass code that + // runs before the attribute is set won't think we're missing a + // contenteditable attr when we actually have one. + SetMayHaveContentEditableAttr(); + } + } + if (!aValue && IsEventAttributeName(aName)) { + if (EventListenerManager* manager = GetExistingListenerManager()) { + manager->RemoveEventHandler(aName, EmptyString()); + } + } + } + + return nsGenericHTMLElementBase::BeforeSetAttr(aNamespaceID, aName, aValue, + aNotify); +} + +nsresult nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNamespaceID == kNameSpaceID_None) { if (IsEventAttributeName(aName) && aValue) { @@ -670,34 +707,83 @@ nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, } else if (aName == nsGkAtoms::dir) { Directionality dir = eDir_LTR; + // A boolean tracking whether we need to recompute our directionality. + // This needs to happen after we update our internal "dir" attribute + // state but before we call SetDirectionalityOnDescendants. + bool recomputeDirectionality = false; + // We don't want to have to keep getting the "dir" attribute in + // IntrinsicState, so we manually recompute our dir-related event states + // here and send the relevant update notifications. + EventStates dirStates; if (aValue && aValue->Type() == nsAttrValue::eEnum) { SetHasValidDir(); + dirStates |= NS_EVENT_STATE_HAS_DIR_ATTR; Directionality dirValue = (Directionality)aValue->GetEnumValue(); if (dirValue == eDir_Auto) { - SetHasDirAuto(); - ClearHasFixedDir(); + dirStates |= NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO; } else { dir = dirValue; SetDirectionality(dir, aNotify); - ClearHasDirAuto(); - SetHasFixedDir(); + if (dirValue == eDir_LTR) { + dirStates |= NS_EVENT_STATE_DIR_ATTR_LTR; + } else { + MOZ_ASSERT(dirValue == eDir_RTL); + dirStates |= NS_EVENT_STATE_DIR_ATTR_RTL; + } } } else { + if (aValue) { + // We have a value, just not a valid one. + dirStates |= NS_EVENT_STATE_HAS_DIR_ATTR; + } ClearHasValidDir(); - ClearHasFixedDir(); if (NodeInfo()->Equals(nsGkAtoms::bdi)) { - SetHasDirAuto(); + dirStates |= NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO; } else { - ClearHasDirAuto(); - dir = RecomputeDirectionality(this, aNotify); + recomputeDirectionality = true; } } + // Now figure out what's changed about our dir states. + EventStates oldDirStates = State() & DIR_ATTR_STATES; + EventStates changedStates = dirStates ^ oldDirStates; + ToggleStates(changedStates, aNotify); + if (recomputeDirectionality) { + dir = RecomputeDirectionality(this, aNotify); + } SetDirectionalityOnDescendants(this, dir, aNotify); + } else if (aName == nsGkAtoms::contenteditable) { + int32_t editableCountDelta = 0; + if (aOldValue && + (aOldValue->Equals(NS_LITERAL_STRING("true"), eIgnoreCase) || + aOldValue->Equals(EmptyString(), eIgnoreCase))) { + editableCountDelta = -1; + } + if (aValue && (aValue->Equals(NS_LITERAL_STRING("true"), eIgnoreCase) || + aValue->Equals(EmptyString(), eIgnoreCase))) { + ++editableCountDelta; + } + ChangeEditableState(editableCountDelta); + } else if (aName == nsGkAtoms::accesskey) { + if (aValue && !aValue->Equals(EmptyString(), eIgnoreCase)) { + SetFlags(NODE_HAS_ACCESSKEY); + RegAccessKey(); + } + } else if (aName == nsGkAtoms::name) { + if (aValue && !aValue->Equals(EmptyString(), eIgnoreCase) && + CanHaveName(NodeInfo()->NameAtom())) { + // This may not be quite right because we can have subclass code run + // before here. But in practice subclasses don't care about this flag, + // and in particular selector matching does not care. Otherwise we'd + // want to handle it like we handle id attributes (in PreIdMaybeChange + // and PostIdMaybeChange). + SetHasName(); + AddToNameTable(aValue->GetAtomValue()); + } } } return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName, - aValue, aNotify); + aValue, aOldValue, aNotify); } EventListenerManager* @@ -818,87 +904,6 @@ nsGenericHTMLElement::SetOn##name_(EventHandlerNonNull* handler) \ #undef FORWARDED_EVENT #undef EVENT -nsresult -nsGenericHTMLElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) -{ - bool contentEditable = aNameSpaceID == kNameSpaceID_None && - aName == nsGkAtoms::contenteditable; - bool accessKey = aName == nsGkAtoms::accesskey && - aNameSpaceID == kNameSpaceID_None; - - int32_t change = 0; - if (contentEditable) { - change = GetContentEditableValue() == eTrue ? -1 : 0; - SetMayHaveContentEditableAttr(); - } - - if (accessKey) { - UnregAccessKey(); - } - - nsresult rv = nsStyledElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, - aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - if (contentEditable) { - if (aValue.IsEmpty() || aValue.LowerCaseEqualsLiteral("true")) { - change += 1; - } - - ChangeEditableState(change); - } - - if (accessKey && !aValue.IsEmpty()) { - SetFlags(NODE_HAS_ACCESSKEY); - RegAccessKey(); - } - - return NS_OK; -} - -nsresult -nsGenericHTMLElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) -{ - bool contentEditable = false; - int32_t contentEditableChange = 0; - - // Check for event handlers - if (aNameSpaceID == kNameSpaceID_None) { - if (aAttribute == nsGkAtoms::name) { - // Have to do this before clearing flag. See RemoveFromNameTable - RemoveFromNameTable(); - ClearHasName(); - } - else if (aAttribute == nsGkAtoms::contenteditable) { - contentEditable = true; - contentEditableChange = GetContentEditableValue() == eTrue ? -1 : 0; - } - else if (aAttribute == nsGkAtoms::accesskey) { - // Have to unregister before clearing flag. See UnregAccessKey - UnregAccessKey(); - UnsetFlags(NODE_HAS_ACCESSKEY); - } - else if (IsEventAttributeName(aAttribute)) { - if (EventListenerManager* manager = GetExistingListenerManager()) { - manager->RemoveEventHandler(aAttribute, EmptyString()); - } - } - } - - nsresult rv = nsGenericHTMLElementBase::UnsetAttr(aNameSpaceID, aAttribute, - aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - if (contentEditable) { - ChangeEditableState(contentEditableChange); - } - - return NS_OK; -} - void nsGenericHTMLElement::GetBaseTarget(nsAString& aBaseTarget) const { @@ -928,19 +933,13 @@ nsGenericHTMLElement::ParseAttribute(int32_t aNamespaceID, if (aAttribute == nsGkAtoms::name) { // Store name as an atom. name="" means that the element has no name, - // not that it has an emptystring as the name. - RemoveFromNameTable(); + // not that it has an empty string as the name. if (aValue.IsEmpty()) { ClearHasName(); return false; } aResult.ParseAtom(aValue); - - if (CanHaveName(NodeInfo()->NameAtom())) { - SetHasName(); - AddToNameTable(aResult.GetAtomValue()); - } return true; } @@ -1758,7 +1757,7 @@ nsGenericHTMLElement::Labels() { MOZ_ASSERT(IsLabelable(), "Labels() only allow labelable elements to use it."); - nsDOMSlots* slots = DOMSlots(); + nsExtendedDOMSlots* slots = ExtendedDOMSlots(); if (!slots->mLabelsList) { slots->mLabelsList = new nsLabelsNodeList(SubtreeRoot(), MatchLabelsElement, @@ -1990,7 +1989,7 @@ nsGenericHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent) nsresult nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { @@ -2023,13 +2022,6 @@ nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } mForm->RemoveElement(this, false); - - // Removing the element from the form can make it not be the default - // control anymore. Go ahead and notify on that change, though we might - // end up readding and becoming the default control again in - // AfterSetAttr. - // FIXME: Bug 656197 - UpdateState(aNotify); } if (aName == nsGkAtoms::form) { @@ -2050,7 +2042,8 @@ nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsresult nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, bool aNotify) { if (aNameSpaceID == kNameSpaceID_None) { // add the control to the hashtable as needed @@ -2079,12 +2072,6 @@ nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } mForm->AddElement(this, false, aNotify); - - // Adding the element to the form can make it be the default control . - // Go ahead and notify on that change. - // Note: no need to notify on CanBeDisabled(), since type attr - // changes can't affect that. - UpdateState(aNotify); } if (aName == nsGkAtoms::form) { @@ -2105,11 +2092,23 @@ nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, - aValue, aNotify); + aValue, aOldValue, aNotify); +} + +nsresult +nsGenericHTMLFormElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) +{ + if (aVisitor.mEvent->IsTrusted() && (aVisitor.mEvent->mMessage == eFocus || + aVisitor.mEvent->mMessage == eBlur)) { + // We have to handle focus/blur event to change focus states in + // PreHandleEvent to prevent it breaks event target chain creation. + aVisitor.mWantsPreHandleEvent = true; + } + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } nsresult -nsGenericHTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +nsGenericHTMLFormElement::PreHandleEvent(EventChainVisitor& aVisitor) { if (aVisitor.mEvent->IsTrusted()) { switch (aVisitor.mEvent->mMessage) { @@ -2133,7 +2132,6 @@ nsGenericHTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor) break; } } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); } diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h index 6d7dc0cef..56812b445 100644 --- a/dom/html/nsGenericHTMLElement.h +++ b/dom/html/nsGenericHTMLElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -465,17 +464,6 @@ public: virtual void UnbindFromTree(bool aDeep = true, bool aNullParent = true) override; - MOZ_ALWAYS_INLINE // Avoid a crashy hook from Avast 10 Beta - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName, - bool aNotify) override; virtual bool IsFocusableInternal(int32_t *aTabIndex, bool aWithMouse) override { bool isFocusable = false; @@ -498,7 +486,8 @@ public: */ bool CheckHandleEventForAnchorsPreconditions( mozilla::EventChainVisitor& aVisitor); - nsresult PreHandleEventForAnchors(mozilla::EventChainPreVisitor& aVisitor); + nsresult GetEventTargetParentForAnchors( + mozilla::EventChainPreVisitor& aVisitor); nsresult PostHandleEventForAnchors(mozilla::EventChainPostVisitor& aVisitor); bool IsHTMLLink(nsIURI** aURI) const; @@ -915,8 +904,13 @@ private: void RegUnRegAccessKey(bool aDoReg); protected: + virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; virtual mozilla::EventListenerManager* GetEventListenerManagerForAttr(nsIAtom* aAttrName, @@ -1221,8 +1215,10 @@ public: virtual IMEState GetDesiredIMEState() override; virtual mozilla::EventStates IntrinsicState() const override; - virtual nsresult PreHandleEvent( + virtual nsresult GetEventTargetParent( mozilla::EventChainPreVisitor& aVisitor) override; + virtual nsresult PreHandleEvent( + mozilla::EventChainVisitor& aVisitor) override; virtual bool IsDisabled() const override; @@ -1264,11 +1260,13 @@ protected: virtual ~nsGenericHTMLFormElement(); virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAttrValueOrString* aValue, + const nsAttrValueOrString* aValue, bool aNotify) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, bool aNotify) override; + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; /** * This method will update the form owner, using @form or looking to a parent. @@ -1309,7 +1307,7 @@ protected: static bool FormIdUpdated(Element* aOldElement, Element* aNewElement, void* aData); - // Returns true if the event should not be handled from PreHandleEvent + // Returns true if the event should not be handled from GetEventTargetParent bool IsElementDisabledForEvents(mozilla::WidgetEvent* aEvent, nsIFrame* aFrame); @@ -1592,6 +1590,15 @@ protected: NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, \ mNodeInfo->Equals(nsGkAtoms::_tag)) +namespace mozilla { +namespace dom { + +typedef nsGenericHTMLElement* (*HTMLContentCreatorFunction)( + already_AddRefed<mozilla::dom::NodeInfo>&&, + mozilla::dom::FromParser aFromParser); + +} // namespace dom +} // namespace mozilla /** * A macro to declare the NS_NewHTMLXXXElement() functions. @@ -1640,6 +1647,13 @@ nsGenericHTMLElement* NS_NewHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); +// Distinct from the above in order to have function pointer that compared unequal +// to a function pointer to the above. +nsGenericHTMLElement* +NS_NewCustomElement( + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); + NS_DECLARE_NS_NEW_HTML_ELEMENT(Shared) NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedList) NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedObject) @@ -1689,7 +1703,7 @@ NS_DECLARE_NS_NEW_HTML_ELEMENT(Pre) NS_DECLARE_NS_NEW_HTML_ELEMENT(Progress) NS_DECLARE_NS_NEW_HTML_ELEMENT(Script) NS_DECLARE_NS_NEW_HTML_ELEMENT(Select) -NS_DECLARE_NS_NEW_HTML_ELEMENT(Shadow) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Slot) NS_DECLARE_NS_NEW_HTML_ELEMENT(Source) NS_DECLARE_NS_NEW_HTML_ELEMENT(Span) NS_DECLARE_NS_NEW_HTML_ELEMENT(Style) diff --git a/dom/html/nsGenericHTMLFrameElement.cpp b/dom/html/nsGenericHTMLFrameElement.cpp index 6e50a4092..1d0b6769a 100644 --- a/dom/html/nsGenericHTMLFrameElement.cpp +++ b/dom/html/nsGenericHTMLFrameElement.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -27,6 +26,7 @@ #include "nsServiceManagerUtils.h" #include "nsSubDocumentFrame.h" #include "nsXULElement.h" +#include "nsAttrValueOrString.h" using namespace mozilla; using namespace mozilla::dom; @@ -334,55 +334,6 @@ nsGenericHTMLFrameElement::UnbindFromTree(bool aDeep, bool aNullParent) nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); } -nsresult -nsGenericHTMLFrameElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) -{ - nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, - aValue, aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src && - (!IsHTMLElement(nsGkAtoms::iframe) || - !HasAttr(kNameSpaceID_None,nsGkAtoms::srcdoc))) { - // Don't propagate error here. The attribute was successfully set, that's - // what we should reflect. - LoadSrc(); - } else if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::name) { - // Propagate "name" to the docshell to make browsing context names live, - // per HTML5. - nsIDocShell *docShell = mFrameLoader ? mFrameLoader->GetExistingDocShell() - : nullptr; - if (docShell) { - docShell->SetName(aValue); - } - } - - return NS_OK; -} - -nsresult -nsGenericHTMLFrameElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) -{ - // Invoke on the superclass. - nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); - NS_ENSURE_SUCCESS(rv, rv); - - if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::name) { - // Propagate "name" to the docshell to make browsing context names live, - // per HTML5. - nsIDocShell *docShell = mFrameLoader ? mFrameLoader->GetExistingDocShell() - : nullptr; - if (docShell) { - docShell->SetName(EmptyString()); - } - } - - return NS_OK; -} - /* static */ int32_t nsGenericHTMLFrameElement::MapScrollingAttribute(const nsAttrValue* aValue) { @@ -399,37 +350,102 @@ nsGenericHTMLFrameElement::MapScrollingAttribute(const nsAttrValue* aValue) return mappedValue; } +static bool +PrincipalAllowsBrowserFrame(nsIPrincipal* aPrincipal) +{ + nsCOMPtr<nsIPermissionManager> permMgr = mozilla::services::GetPermissionManager(); + NS_ENSURE_TRUE(permMgr, false); + uint32_t permission = nsIPermissionManager::DENY_ACTION; + nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, "browser", &permission); + NS_ENSURE_SUCCESS(rv, false); + return permission == nsIPermissionManager::ALLOW_ACTION; +} + /* virtual */ nsresult nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, - bool aNotify) -{ - if (aName == nsGkAtoms::scrolling && aNameSpaceID == kNameSpaceID_None) { - if (mFrameLoader) { - nsIDocShell* docshell = mFrameLoader->GetExistingDocShell(); - nsCOMPtr<nsIScrollable> scrollable = do_QueryInterface(docshell); - if (scrollable) { - int32_t cur; - scrollable->GetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X, &cur); - int32_t val = MapScrollingAttribute(aValue); - if (cur != val) { - scrollable->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X, val); - scrollable->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y, val); - RefPtr<nsPresContext> presContext; - docshell->GetPresContext(getter_AddRefs(presContext)); - nsIPresShell* shell = presContext ? presContext->GetPresShell() : nullptr; - nsIFrame* rootScroll = shell ? shell->GetRootScrollFrame() : nullptr; - if (rootScroll) { - shell->FrameNeedsReflow(rootScroll, nsIPresShell::eStyleChange, - NS_FRAME_IS_DIRTY); + const nsAttrValue* aOldValue, bool aNotify) +{ + if (aValue) { + nsAttrValueOrString value(aValue); + AfterMaybeChangeAttr(aNameSpaceID, aName, &value, aNotify); + } else { + AfterMaybeChangeAttr(aNameSpaceID, aName, nullptr, aNotify); + } + + if (aNameSpaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::scrolling) { + if (mFrameLoader) { + nsIDocShell* docshell = mFrameLoader->GetExistingDocShell(); + nsCOMPtr<nsIScrollable> scrollable = do_QueryInterface(docshell); + if (scrollable) { + int32_t cur; + scrollable->GetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X, &cur); + int32_t val = MapScrollingAttribute(aValue); + if (cur != val) { + scrollable->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X, val); + scrollable->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y, val); + RefPtr<nsPresContext> presContext; + docshell->GetPresContext(getter_AddRefs(presContext)); + nsIPresShell* shell = presContext ? presContext->GetPresShell() : nullptr; + nsIFrame* rootScroll = shell ? shell->GetRootScrollFrame() : nullptr; + if (rootScroll) { + shell->FrameNeedsReflow(rootScroll, nsIPresShell::eStyleChange, + NS_FRAME_IS_DIRTY); + } } } } + } else if (aName == nsGkAtoms::mozbrowser) { + mReallyIsBrowser = !!aValue && BrowserFramesEnabled() && + PrincipalAllowsBrowserFrame(NodePrincipal()); } } return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, - aNotify); + aOldValue, aNotify); +} + +nsresult +nsGenericHTMLFrameElement::OnAttrSetButNotChanged(int32_t aNamespaceID, + nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) +{ + AfterMaybeChangeAttr(aNamespaceID, aName, &aValue, aNotify); + + return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName, + aValue, aNotify); +} + +void +nsGenericHTMLFrameElement::AfterMaybeChangeAttr(int32_t aNamespaceID, + nsIAtom* aName, + const nsAttrValueOrString* aValue, + bool aNotify) +{ + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::src) { + if (aValue && (!IsHTMLElement(nsGkAtoms::iframe) || + !HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc))) { + // Don't propagate error here. The attribute was successfully set, + // that's what we should reflect. + LoadSrc(); + } + } else if (aName == nsGkAtoms::name) { + // Propagate "name" to the docshell to make browsing context names live, + // per HTML5. + nsIDocShell* docShell = mFrameLoader ? mFrameLoader->GetExistingDocShell() + : nullptr; + if (docShell) { + if (aValue) { + docShell->SetName(aValue->String()); + } else { + docShell->SetName(EmptyString()); + } + } + } + } } void @@ -503,28 +519,7 @@ nsGenericHTMLFrameElement::BrowserFramesEnabled() /* [infallible] */ nsresult nsGenericHTMLFrameElement::GetReallyIsBrowserOrApp(bool *aOut) { - *aOut = false; - - // Fail if browser frames are globally disabled. - if (!nsGenericHTMLFrameElement::BrowserFramesEnabled()) { - return NS_OK; - } - - // Fail if this frame doesn't have the mozbrowser attribute. - if (!GetBoolAttr(nsGkAtoms::mozbrowser)) { - return NS_OK; - } - - // Fail if the node principal isn't trusted. - nsIPrincipal *principal = NodePrincipal(); - nsCOMPtr<nsIPermissionManager> permMgr = - services::GetPermissionManager(); - NS_ENSURE_TRUE(permMgr, NS_OK); - - uint32_t permission = nsIPermissionManager::DENY_ACTION; - nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "browser", &permission); - NS_ENSURE_SUCCESS(rv, NS_OK); - *aOut = permission == nsIPermissionManager::ALLOW_ACTION; + *aOut = mReallyIsBrowser; return NS_OK; } diff --git a/dom/html/nsGenericHTMLFrameElement.h b/dom/html/nsGenericHTMLFrameElement.h index d9c2df9d5..5b7caa251 100644 --- a/dom/html/nsGenericHTMLFrameElement.h +++ b/dom/html/nsGenericHTMLFrameElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -36,6 +35,7 @@ public: , mIsPrerendered(false) , mBrowserFrameListenersRegistered(false) , mFrameLoaderCreationDisallowed(false) + , mReallyIsBrowser(false) { } @@ -52,19 +52,7 @@ public: bool aCompileEventHandlers) override; virtual void UnbindFromTree(bool aDeep = true, bool aNullParent = true) override; - nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, bool aNotify) - { - return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify); - } - virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsIAtom* aPrefix, const nsAString& aValue, - bool aNotify) override; - virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify) override; - virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, - const nsAttrValue* aValue, - bool aNotify) override; + virtual void DestroyContent() override; nsresult CopyInnerTo(mozilla::dom::Element* aDest); @@ -109,6 +97,14 @@ protected: nsresult GetContentDocument(nsIDOMDocument** aContentDocument); already_AddRefed<nsPIDOMWindowOuter> GetContentWindow(); + virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAttrValue* aValue, + const nsAttrValue* aOldValue, + bool aNotify) override; + virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString& aValue, + bool aNotify) override; + RefPtr<nsFrameLoader> mFrameLoader; nsCOMPtr<nsPIDOMWindowOuter> mOpenerWindow; @@ -122,6 +118,7 @@ protected: bool mIsPrerendered; bool mBrowserFrameListenersRegistered; bool mFrameLoaderCreationDisallowed; + bool mReallyIsBrowser; // This flag is only used by <iframe>. See HTMLIFrameElement:: // FullscreenFlag() for details. It is placed here so that we @@ -130,6 +127,18 @@ protected: private: void GetManifestURL(nsAString& aOut); + + /** + * This function is called by AfterSetAttr and OnAttrSetButNotChanged. + * It will be called whether the value is being set or unset. + * + * @param aNamespaceID the namespace of the attr being set + * @param aName the localname of the attribute being set + * @param aValue the value being set or null if the value is being unset + * @param aNotify Whether we plan to notify document observers. + */ + void AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName, + const nsAttrValueOrString* aValue, bool aNotify); }; #endif // nsGenericHTMLFrameElement_h diff --git a/dom/html/nsHTMLContentSink.cpp b/dom/html/nsHTMLContentSink.cpp index 409b225ef..938fcd169 100644 --- a/dom/html/nsHTMLContentSink.cpp +++ b/dom/html/nsHTMLContentSink.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -14,6 +13,7 @@ #include "nsContentSink.h" #include "nsCOMPtr.h" +#include "nsHTMLTags.h" #include "nsReadableUtils.h" #include "nsUnicharUtils.h" #include "nsIHTMLContentSink.h" @@ -30,6 +30,7 @@ #include "mozilla/Logging.h" #include "nsNodeUtils.h" #include "nsIContent.h" +#include "mozilla/dom/CustomElementRegistry.h" #include "mozilla/dom/Element.h" #include "mozilla/Preferences.h" @@ -59,8 +60,6 @@ #include "nsIScriptGlobalObject.h" #include "nsNameSpaceManager.h" -#include "nsIParserService.h" - #include "nsIStyleSheetLinkingElement.h" #include "nsITimer.h" #include "nsError.h" @@ -84,10 +83,6 @@ using namespace mozilla::dom; //---------------------------------------------------------------------- -typedef nsGenericHTMLElement* - (*contentCreatorCallback)(already_AddRefed<mozilla::dom::NodeInfo>&&, - FromParser aFromParser); - nsGenericHTMLElement* NS_NewHTMLNOTUSEDElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, FromParser aFromParser) @@ -96,14 +91,12 @@ NS_NewHTMLNOTUSEDElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, return nullptr; } -#define HTML_TAG(_tag, _classname) NS_NewHTML##_classname##Element, -#define HTML_HTMLELEMENT_TAG(_tag) NS_NewHTMLElement, +#define HTML_TAG(_tag, _classname, _interfacename) NS_NewHTML##_classname##Element, #define HTML_OTHER(_tag) NS_NewHTMLNOTUSEDElement, -static const contentCreatorCallback sContentCreatorCallbacks[] = { +static const HTMLContentCreatorFunction sHTMLContentCreatorFunctions[] = { NS_NewHTMLUnknownElement, #include "nsHTMLTagList.h" #undef HTML_TAG -#undef HTML_HTMLELEMENT_TAG #undef HTML_OTHER NS_NewHTMLUnknownElement }; @@ -234,29 +227,144 @@ public: int32_t mStackPos; }; +static void +DoCustomElementCreate(Element** aElement, nsIDocument* aDoc, nsIAtom* aLocalName, + CustomElementConstructor* aConstructor, ErrorResult& aRv) +{ + RefPtr<Element> element = + aConstructor->Construct("Custom Element Create", aRv); + if (aRv.Failed()) { + return; + } + + if (!element || !element->IsHTMLElement()) { + aRv.ThrowTypeError<MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE>(NS_LITERAL_STRING("HTMLElement")); + return; + } + + if (aDoc != element->OwnerDoc() || element->GetParentNode() || + element->HasChildren() || element->GetAttrCount() || + element->NodeInfo()->NameAtom() != aLocalName) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } + + element.forget(aElement); +} + nsresult NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, - FromParser aFromParser, const nsAString* aIs) + FromParser aFromParser, const nsAString* aIs, + mozilla::dom::CustomElementDefinition* aDefinition) { *aResult = nullptr; RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo; - nsIParserService* parserService = nsContentUtils::GetParserService(); - if (!parserService) - return NS_ERROR_OUT_OF_MEMORY; - nsIAtom *name = nodeInfo->NameAtom(); + RefPtr<nsIAtom> tagAtom = nodeInfo->NameAtom(); + RefPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : tagAtom; NS_ASSERTION(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML), "Trying to HTML elements that don't have the XHTML namespace"); - int32_t tag = parserService->HTMLCaseSensitiveAtomTagToId(name); + int32_t tag = nsHTMLTags::CaseSensitiveAtomTagToId(name); - // Per the Custom Element specification, unknown tags that are valid custom - // element names should be HTMLElement instead of HTMLUnknownElement. bool isCustomElementName = (tag == eHTMLTag_userdefined && nsContentUtils::IsCustomElementName(name)); + bool isCustomElement = isCustomElementName || aIs; + MOZ_ASSERT_IF(aDefinition, isCustomElement); + + // https://dom.spec.whatwg.org/#concept-create-element + // We only handle the "synchronous custom elements flag is set" now. + // For the unset case (e.g. cloning a node), see bug 1319342 for that. + // Step 4. + CustomElementDefinition* definition = aDefinition; + if (CustomElementRegistry::IsCustomElementEnabled() && isCustomElement && + !definition) { + MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())); + definition = + nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(), + nodeInfo->NameAtom(), + nodeInfo->NamespaceID(), + typeAtom); + } + + // It might be a problem that parser synchronously calls constructor, so filed + // bug 1378079 to figure out what we should do for parser case. + if (definition) { + /* + * Synchronous custom elements flag is determined by 3 places in spec, + * 1) create an element for a token, the flag is determined by + * "will execute script" which is not originally created + * for the HTML fragment parsing algorithm. + * 2) createElement and createElementNS, the flag is the same as + * NOT_FROM_PARSER. + * 3) clone a node, our implementation will not go into this function. + * For the unset case which is non-synchronous only applied for + * inner/outerHTML. + */ + bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT || + aFromParser == dom::NOT_FROM_PARSER; + // Per discussion in https://github.com/w3c/webcomponents/issues/635, + // use entry global in those places that are called from JS APIs and use the + // node document's global object if it is called from parser. + nsIGlobalObject* global; + if (aFromParser == dom::NOT_FROM_PARSER) { + global = GetEntryGlobal(); + } else { + global = nodeInfo->GetDocument()->GetScopeObject(); + } + if (!global) { + // In browser chrome code, one may have access to a document which doesn't + // have scope object anymore. + return NS_ERROR_FAILURE; + } + + AutoEntryScript aes(global, "create custom elements"); + JSContext* cx = aes.cx(); + ErrorResult rv; + + // Step 5. + if (definition->IsCustomBuiltIn()) { + // SetupCustomElement() should be called with an element that don't have + // CustomElementData setup, if not we will hit the assertion in + // SetCustomElementData(). + // Built-in element + *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take(); + (*aResult)->SetCustomElementData(new CustomElementData(typeAtom)); + if (synchronousCustomElements) { + CustomElementRegistry::Upgrade(*aResult, definition, rv); + if (rv.MaybeSetPendingException(cx)) { + aes.ReportException(); + } + } else { + nsContentUtils::EnqueueUpgradeReaction(*aResult, definition); + } + + return NS_OK; + } + + // Step 6.1. + if (synchronousCustomElements) { + DoCustomElementCreate(aResult, nodeInfo->GetDocument(), + nodeInfo->NameAtom(), + definition->mConstructor, rv); + if (rv.MaybeSetPendingException(cx)) { + NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(), aFromParser)); + } + return NS_OK; + } + + // Step 6.2. + NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser)); + (*aResult)->SetCustomElementData(new CustomElementData(definition->mType)); + nsContentUtils::EnqueueUpgradeReaction(*aResult, definition); + return NS_OK; + } + + // Per the Custom Element specification, unknown tags that are valid custom + // element names should be HTMLElement instead of HTMLUnknownElement. if (isCustomElementName) { NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser)); } else { @@ -267,8 +375,8 @@ NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& return NS_ERROR_OUT_OF_MEMORY; } - if (isCustomElementName || aIs) { - nsContentUtils::SetupCustomElement(*aResult, aIs); + if (CustomElementRegistry::IsCustomElementEnabled() && isCustomElement) { + (*aResult)->SetCustomElementData(new CustomElementData(typeAtom)); } return NS_OK; @@ -283,7 +391,7 @@ CreateHTMLElement(uint32_t aNodeType, aNodeType == eHTMLTag_userdefined, "aNodeType is out of bounds"); - contentCreatorCallback cb = sContentCreatorCallbacks[aNodeType]; + HTMLContentCreatorFunction cb = sHTMLContentCreatorFunctions[aNodeType]; NS_ASSERTION(cb != NS_NewHTMLNOTUSEDElement, "Don't know how to construct tag element!"); diff --git a/dom/html/nsHTMLDNSPrefetch.cpp b/dom/html/nsHTMLDNSPrefetch.cpp index 2ddc8476d..6a2d0e1d6 100644 --- a/dom/html/nsHTMLDNSPrefetch.cpp +++ b/dom/html/nsHTMLDNSPrefetch.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsHTMLDNSPrefetch.h b/dom/html/nsHTMLDNSPrefetch.h index 18da98f26..094471e36 100644 --- a/dom/html/nsHTMLDNSPrefetch.h +++ b/dom/html/nsHTMLDNSPrefetch.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp index b0747fb04..bc62f9753 100644 --- a/dom/html/nsHTMLDocument.cpp +++ b/dom/html/nsHTMLDocument.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -1014,26 +1013,6 @@ nsHTMLDocument::SetDomain(const nsAString& aDomain, ErrorResult& rv) rv = NodePrincipal()->SetDomain(newURI); } -nsGenericHTMLElement* -nsHTMLDocument::GetBody() -{ - Element* html = GetHtmlElement(); - if (!html) { - return nullptr; - } - - for (nsIContent* child = html->GetFirstChild(); - child; - child = child->GetNextSibling()) { - if (child->IsHTMLElement(nsGkAtoms::body) || - child->IsHTMLElement(nsGkAtoms::frameset)) { - return static_cast<nsGenericHTMLElement*>(child); - } - } - - return nullptr; -} - NS_IMETHODIMP nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody) { @@ -1055,31 +1034,6 @@ nsHTMLDocument::SetBody(nsIDOMHTMLElement* aBody) return rv.StealNSResult(); } -void -nsHTMLDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv) -{ - nsCOMPtr<Element> root = GetRootElement(); - - // The body element must be either a body tag or a frameset tag. And we must - // have a html root tag, otherwise GetBody will not return the newly set - // body. - if (!newBody || - !newBody->IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset) || - !root || !root->IsHTMLElement() || - !root->IsHTMLElement(nsGkAtoms::html)) { - rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR); - return; - } - - // Use DOM methods so that we pass through the appropriate security checks. - nsCOMPtr<Element> currentBody = GetBodyElement(); - if (currentBody) { - root->ReplaceChild(*newBody, *currentBody, rv); - } else { - root->AppendChild(*newBody, rv); - } -} - NS_IMETHODIMP nsHTMLDocument::GetHead(nsIDOMHTMLHeadElement** aHead) { @@ -1447,6 +1401,11 @@ nsHTMLDocument::Open(JSContext* cx, return nullptr; } + if (ShouldThrowOnDynamicMarkupInsertion()) { + aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); + return nullptr; + } + // Set up the content type for insertion nsAutoCString contentType; contentType.AssignLiteral("text/html"); @@ -1657,6 +1616,11 @@ nsHTMLDocument::Close(ErrorResult& rv) return; } + if (ShouldThrowOnDynamicMarkupInsertion()) { + rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); + return; + } + if (!mParser || !mParser->IsScriptCreated()) { return; } @@ -1732,6 +1696,10 @@ nsHTMLDocument::WriteCommon(JSContext *cx, return NS_ERROR_DOM_INVALID_STATE_ERR; } + if (ShouldThrowOnDynamicMarkupInsertion()) { + return NS_ERROR_DOM_INVALID_STATE_ERR; + } + if (mParserAborted) { // Hixie says aborting the parser doesn't undefine the insertion point. // However, since we null out mParser in that case, we track the @@ -2128,7 +2096,7 @@ nsHTMLDocument::GetSupportedNames(nsTArray<nsString>& aNames) nsIdentifierMapEntry* entry = iter.Get(); if (entry->HasNameElement() || entry->HasIdElementExposedAsHTMLDocumentProperty()) { - aNames.AppendElement(entry->GetKey()); + aNames.AppendElement(entry->GetKeyAsString()); } } } diff --git a/dom/html/nsHTMLDocument.h b/dom/html/nsHTMLDocument.h index 1fa81f6cd..8eec4c0c4 100644 --- a/dom/html/nsHTMLDocument.h +++ b/dom/html/nsHTMLDocument.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -155,10 +154,7 @@ public: virtual void RemovedFromDocShell() override; - virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId) override - { - return nsDocument::GetElementById(aElementId); - } + using mozilla::dom::DocumentOrShadowRoot::GetElementById; virtual void DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const override; // DocAddSizeOfIncludingThis is inherited from nsIDocument. @@ -175,8 +171,8 @@ public: JS::MutableHandle<JSObject*> aRetval, mozilla::ErrorResult& rv); void GetSupportedNames(nsTArray<nsString>& aNames); - nsGenericHTMLElement *GetBody(); - void SetBody(nsGenericHTMLElement* aBody, mozilla::ErrorResult& rv); + using nsIDocument::GetBody; + using nsIDocument::SetBody; mozilla::dom::HTMLSharedElement *GetHead() { return static_cast<mozilla::dom::HTMLSharedElement*>(GetHeadElement()); } diff --git a/dom/html/nsIConstraintValidation.cpp b/dom/html/nsIConstraintValidation.cpp index db69cba07..318b6851b 100644 --- a/dom/html/nsIConstraintValidation.cpp +++ b/dom/html/nsIConstraintValidation.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsIConstraintValidation.h b/dom/html/nsIConstraintValidation.h index c15bf846b..c94120247 100644 --- a/dom/html/nsIConstraintValidation.h +++ b/dom/html/nsIConstraintValidation.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsIForm.h b/dom/html/nsIForm.h index 91bb7ac86..44eedc510 100644 --- a/dom/html/nsIForm.h +++ b/dom/html/nsIForm.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsIFormControl.h b/dom/html/nsIFormControl.h index 22f1d08b3..0a844a567 100644 --- a/dom/html/nsIFormControl.h +++ b/dom/html/nsIFormControl.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsIFormProcessor.h b/dom/html/nsIFormProcessor.h index b18305ac4..ad92d7597 100644 --- a/dom/html/nsIFormProcessor.h +++ b/dom/html/nsIFormProcessor.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsIHTMLCollection.h b/dom/html/nsIHTMLCollection.h index 7dbfe8766..d27f82d1f 100644 --- a/dom/html/nsIHTMLCollection.h +++ b/dom/html/nsIHTMLCollection.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsIHTMLDocument.h b/dom/html/nsIHTMLDocument.h index 8dbee1170..ce7ad47c7 100644 --- a/dom/html/nsIHTMLDocument.h +++ b/dom/html/nsIHTMLDocument.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsIRadioGroupContainer.h b/dom/html/nsIRadioGroupContainer.h index 3d530a723..bee3bf8df 100644 --- a/dom/html/nsIRadioGroupContainer.h +++ b/dom/html/nsIRadioGroupContainer.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsIRadioVisitor.h b/dom/html/nsIRadioVisitor.h index 425a50692..abaaa573c 100644 --- a/dom/html/nsIRadioVisitor.h +++ b/dom/html/nsIRadioVisitor.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsITextControlElement.h b/dom/html/nsITextControlElement.h index 9adbf377e..5c922b7c5 100644 --- a/dom/html/nsITextControlElement.h +++ b/dom/html/nsITextControlElement.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsRadioVisitor.cpp b/dom/html/nsRadioVisitor.cpp index a3f8a34f8..730d4793c 100644 --- a/dom/html/nsRadioVisitor.cpp +++ b/dom/html/nsRadioVisitor.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsRadioVisitor.h b/dom/html/nsRadioVisitor.h index b33d2e4e5..84be7ab85 100644 --- a/dom/html/nsRadioVisitor.h +++ b/dom/html/nsRadioVisitor.h @@ -1,5 +1,4 @@ /* -*- 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/. */ diff --git a/dom/html/nsTextEditorState.cpp b/dom/html/nsTextEditorState.cpp index 25be6016c..b25b14ece 100644 --- a/dom/html/nsTextEditorState.cpp +++ b/dom/html/nsTextEditorState.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -2214,6 +2213,23 @@ nsTextEditorState::SetValue(const nsAString& aValue, uint32_t aFlags) return true; } +bool +nsTextEditorState::HasNonEmptyValue() +{ + if (mEditor && mBoundFrame && mEditorInitialized && + !mIsCommittingComposition) { + bool empty; + nsresult rv = mEditor->GetDocumentIsEmpty(&empty); + if (NS_SUCCEEDED(rv)) { + return !empty; + } + } + + nsAutoString value; + GetValue(value, true); + return !value.IsEmpty(); +} + void nsTextEditorState::InitializeKeyboardEventListeners() { diff --git a/dom/html/nsTextEditorState.h b/dom/html/nsTextEditorState.h index caf5e8eed..5abc88d44 100644 --- a/dom/html/nsTextEditorState.h +++ b/dom/html/nsTextEditorState.h @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -157,6 +156,11 @@ public: }; MOZ_MUST_USE bool SetValue(const nsAString& aValue, uint32_t aFlags); void GetValue(nsAString& aValue, bool aIgnoreWrap) const; + bool HasNonEmptyValue(); + // The following methods are for textarea element to use whether default + // value or not. + // XXX We might have to add assertion when it is into editable, + // or reconsider fixing bug 597525 to remove these. void EmptyValue() { if (mValue) mValue->Truncate(); } bool IsEmpty() const { return mValue ? mValue->IsEmpty() : true; } 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 000000000..8446d7f26 --- /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 000000000..6f4953637 --- /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 000000000..e6c8c505e --- /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 000000000..6530a0ae4 --- /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 dd6339edf..570c07358 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 27a13e7c9..82e773abb 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 diff --git a/dom/html/test/mochitest.ini b/dom/html/test/mochitest.ini index 4a50a9c3f..5c9c66e61 100644 --- a/dom/html/test/mochitest.ini +++ b/dom/html/test/mochitest.ini @@ -569,7 +569,6 @@ support-files = file_cookiemanager.js support-files = file_bug871161-1.html file_bug871161-2.html [test_bug1013316.html] [test_hash_encoded.html] -[test_bug1081037.html] [test_window_open_close.html] tags = openwindow [test_viewport_resize.html] diff --git a/dom/html/test/test_bug1081037.html b/dom/html/test/test_bug1081037.html deleted file mode 100644 index 9d8782580..000000000 --- a/dom/html/test/test_bug1081037.html +++ /dev/null @@ -1,133 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=1081037 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 1081037</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> - <script type="application/javascript"> - - /** Test for Bug 1081037 **/ - -function shouldThrow(fun, msg, ex, todo) { - try { - fun(); - ok(todo, msg); - } catch (e) { - ok(new RegExp(ex).test(e), msg + " (thrown:" + e + ")") - } -} - -var Foo = document.registerElement('x-foo', { - prototype: {bar: 5} -}); - -Foo.prototype.bar = 6; -var foo = new Foo(); -is(foo.bar, 6, "prototype of the ctor returned from registerElement works"); - -var protoDesc = Object.getOwnPropertyDescriptor(Foo, "prototype"); -is(protoDesc.configurable, false, "proto should be non-configurable"); -is(protoDesc.enumerable, false, "proto should be non-enumerable"); -is(protoDesc.writable, false, "proto should be non-writable"); - -// TODO: FIXME! -shouldThrow(function() { - document.registerElement('x-foo2', { - prototype: Foo.prototype - }); - }, - "if proto is an interface prototype object, registerElement should throw", - "not supported", - /* todo = */ true); - -var nonConfigReadonlyProto = Object.create(HTMLElement.prototype, - { constructor: { configurable: false, writable: false, value: 42 } }); - -shouldThrow(function() { - document.registerElement('x-nonconfig-readonly', { - prototype: nonConfigReadonlyProto - }); - }, - "non-configurable and not-writable constructor property", - "not supported"); - - -// this is not defined in current spec: -var readonlyProto = Object.create(HTMLElement.prototype, - { constructor: { configurable: true, writable: false, value: 42 } }); - -var Readonly = document.registerElement('x-nonconfig-readonly', { - prototype: readonlyProto -}); - -is(Readonly.prototype, readonlyProto, "configurable readonly constructor property"); - -var handler = { - getOwnPropertyDescriptor: function(target, name) { - return name == "constructor" ? undefined : Object.getOwnPropertyDescriptor(target,name); - }, - defineProperty: function(target, name, propertyDescriptor) { - if (name == "constructor") { - throw "spec this"; - } - - return Object.defineProperty(target, name, propertyDescriptor); - }, - has: function(target, name) { - if (name == "constructor") { - return false; - } - return name in target; - } -}; -var proxy = new Proxy({}, handler); - -shouldThrow(function() { - document.registerElement('x-proxymagic', { - prototype: proxy - }); - }, - "proxy magic", - "spec this"); - -var getOwn = 0; -var defineProp = 0; -var handler2 = { - getOwnPropertyDescriptor: function(target, name) { - if (name == "constructor") { - getOwn++; - } - return Object.getOwnPropertyDescriptor(target,name); - }, - defineProperty: function(target, name, propertyDescriptor) { - if (name == "constructor") { - defineProp++; - } - return Object.defineProperty(target, name, propertyDescriptor); - } -}; -var proxy2 = new Proxy({}, handler2); - -document.registerElement('x-proxymagic2', { - prototype: proxy2 -}); - -is(getOwn, 1, "number of getOwnPropertyDescriptor calls from registerElement: " + getOwn); -is(defineProp, 1, "number of defineProperty calls from registerElement: " + defineProp); - - </script> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1081037">Mozilla Bug 1081037</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -</pre> -</body> -</html> |