mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 508725 - Part 1: Add content flag representing whether an element is in a style scope. r=dbaron
This commit is contained in:
parent
ed9b0b2817
commit
993c756dda
@ -1319,6 +1319,9 @@ private:
|
||||
NodeHasDirAuto,
|
||||
// Set if a node in the node's parent chain has dir=auto.
|
||||
NodeAncestorHasDirAuto,
|
||||
// Set if the element is in the scope of a scoped style sheet; this flag is
|
||||
// only accurate for elements bounds to a document
|
||||
ElementIsInStyleScope,
|
||||
// Guard value
|
||||
BooleanFlagCount
|
||||
};
|
||||
@ -1435,6 +1438,20 @@ public:
|
||||
|
||||
bool NodeOrAncestorHasDirAuto() const
|
||||
{ return HasDirAuto() || AncestorHasDirAuto(); }
|
||||
|
||||
void SetIsElementInStyleScope(bool aValue) {
|
||||
MOZ_ASSERT(IsElement(), "SetIsInStyleScope on a non-Element node");
|
||||
SetBoolFlag(ElementIsInStyleScope, aValue);
|
||||
}
|
||||
void SetIsElementInStyleScope() {
|
||||
MOZ_ASSERT(IsElement(), "SetIsInStyleScope on a non-Element node");
|
||||
SetBoolFlag(ElementIsInStyleScope);
|
||||
}
|
||||
void ClearIsElementInStyleScope() {
|
||||
MOZ_ASSERT(IsElement(), "ClearIsInStyleScope on a non-Element node");
|
||||
ClearBoolFlag(ElementIsInStyleScope);
|
||||
}
|
||||
bool IsElementInStyleScope() const { return GetBoolFlag(ElementIsInStyleScope); }
|
||||
protected:
|
||||
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
|
||||
void SetInDocument() { SetBoolFlag(IsInDocument); }
|
||||
@ -1455,7 +1472,7 @@ protected:
|
||||
bool HasLockedStyleStates() const
|
||||
{ return GetBoolFlag(ElementHasLockedStyleStates); }
|
||||
|
||||
void SetSubtreeRootPointer(nsINode* aSubtreeRoot)
|
||||
void SetSubtreeRootPointer(nsINode* aSubtreeRoot)
|
||||
{
|
||||
NS_ASSERTION(aSubtreeRoot, "aSubtreeRoot can never be null!");
|
||||
NS_ASSERTION(!(IsNodeOfType(eCONTENT) && IsInDoc()), "Shouldn't be here!");
|
||||
|
@ -1155,6 +1155,9 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES |
|
||||
// And the restyle bits
|
||||
ELEMENT_ALL_RESTYLE_FLAGS);
|
||||
|
||||
// Propagate scoped style sheet tracking bit.
|
||||
SetIsElementInStyleScope(mParent->IsElementInStyleScope());
|
||||
} else {
|
||||
// If we're not in the doc, update our subtree pointer.
|
||||
SetSubtreeRootPointer(aParent->SubtreeRoot());
|
||||
|
@ -12,9 +12,10 @@
|
||||
|
||||
#include "nsStyleLinkElement.h"
|
||||
|
||||
#include "nsIContent.h"
|
||||
#include "mozilla/css/Loader.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsCSSStyleSheet.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMComment.h"
|
||||
#include "nsIDOMNode.h"
|
||||
@ -26,6 +27,9 @@
|
||||
#include "nsUnicharInputStream.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
nsStyleLinkElement::nsStyleLinkElement()
|
||||
: mDontLoadStyle(false)
|
||||
, mUpdatesEnabled(true)
|
||||
@ -203,6 +207,87 @@ nsStyleLinkElement::UpdateStyleSheetInternal(nsIDocument *aOldDocument,
|
||||
aForceUpdate);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsScopedStyleElement(nsIContent* aContent)
|
||||
{
|
||||
// This is quicker than, say, QIing aContent to nsStyleLinkElement
|
||||
// and then calling its virtual GetStyleSheetInfo method to find out
|
||||
// if it is scoped.
|
||||
return aContent->IsHTML(nsGkAtoms::style) &&
|
||||
aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scoped);
|
||||
}
|
||||
|
||||
static void
|
||||
SetIsElementInStyleScopeFlagOnSubtree(Element* aElement)
|
||||
{
|
||||
if (aElement->IsElementInStyleScope()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aElement->SetIsElementInStyleScope();
|
||||
|
||||
nsIContent* n = aElement->GetNextNode(aElement);
|
||||
while (n) {
|
||||
if (n->IsElementInStyleScope()) {
|
||||
n = n->GetNextNonChildNode(aElement);
|
||||
} else {
|
||||
if (n->IsElement()) {
|
||||
n->SetIsElementInStyleScope();
|
||||
}
|
||||
n = n->GetNextNode(aElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
HasScopedStyleSheetChild(nsIContent* aContent)
|
||||
{
|
||||
for (nsIContent* n = aContent->GetFirstChild(); n; n = n->GetNextSibling()) {
|
||||
if (IsScopedStyleElement(n)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Called when aElement has had a <style scoped> child removed.
|
||||
static void
|
||||
UpdateIsElementInStyleScopeFlagOnSubtree(Element* aElement)
|
||||
{
|
||||
NS_ASSERTION(aElement->IsElementInStyleScope(),
|
||||
"only call UpdateIsElementInStyleScopeFlagOnSubtree on a "
|
||||
"subtree that has IsElementInStyleScope boolean flag set");
|
||||
|
||||
if (HasScopedStyleSheetChild(aElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
aElement->ClearIsElementInStyleScope();
|
||||
|
||||
nsIContent* n = aElement->GetNextNode(aElement);
|
||||
while (n) {
|
||||
if (HasScopedStyleSheetChild(n)) {
|
||||
n = n->GetNextNonChildNode(aElement);
|
||||
} else {
|
||||
if (n->IsElement()) {
|
||||
n->ClearIsElementInStyleScope();
|
||||
}
|
||||
n = n->GetNextNode(aElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Element*
|
||||
GetScopeElement(nsIStyleSheet* aSheet)
|
||||
{
|
||||
nsRefPtr<nsCSSStyleSheet> cssStyleSheet = do_QueryObject(aSheet);
|
||||
if (!cssStyleSheet) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return cssStyleSheet->GetScopeElement();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument *aOldDocument,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
@ -212,6 +297,11 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument *aOldDocument,
|
||||
{
|
||||
*aWillNotify = false;
|
||||
|
||||
nsCOMPtr<nsIContent> thisContent;
|
||||
CallQueryInterface(this, getter_AddRefs(thisContent));
|
||||
|
||||
Element* oldScopeElement = GetScopeElement(mStyleSheet);
|
||||
|
||||
if (mStyleSheet && aOldDocument) {
|
||||
// We're removing the link element from the document, unload the
|
||||
// stylesheet. We want to do this even if updates are disabled, since
|
||||
@ -221,15 +311,15 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument *aOldDocument,
|
||||
aOldDocument->RemoveStyleSheet(mStyleSheet);
|
||||
aOldDocument->EndUpdate(UPDATE_STYLE);
|
||||
nsStyleLinkElement::SetStyleSheet(nullptr);
|
||||
if (oldScopeElement) {
|
||||
UpdateIsElementInStyleScopeFlagOnSubtree(oldScopeElement);
|
||||
}
|
||||
}
|
||||
|
||||
if (mDontLoadStyle || !mUpdatesEnabled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> thisContent;
|
||||
QueryInterface(NS_GET_IID(nsIContent), getter_AddRefs(thisContent));
|
||||
|
||||
NS_ENSURE_TRUE(thisContent, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = thisContent->GetDocument();
|
||||
@ -264,14 +354,21 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument *aOldDocument,
|
||||
}
|
||||
|
||||
nsAutoString title, type, media;
|
||||
bool isScoped;
|
||||
bool isAlternate;
|
||||
|
||||
GetStyleSheetInfo(title, type, media, &isAlternate);
|
||||
GetStyleSheetInfo(title, type, media, &isScoped, &isAlternate);
|
||||
|
||||
if (!type.LowerCaseEqualsLiteral("text/css")) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Element* scopeElement = isScoped ? thisContent->GetParentElement() : nullptr;
|
||||
if (scopeElement) {
|
||||
NS_ASSERTION(isInline, "non-inline style must not have scope element");
|
||||
SetIsElementInStyleScopeFlagOnSubtree(scopeElement);
|
||||
}
|
||||
|
||||
bool doneLoading = false;
|
||||
nsresult rv = NS_OK;
|
||||
if (isInline) {
|
||||
|
@ -73,6 +73,7 @@ protected:
|
||||
virtual void GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate) = 0;
|
||||
|
||||
nsIStyleSheet* GetStyleSheet() { return mStyleSheet; }
|
||||
|
@ -103,6 +103,7 @@ protected:
|
||||
virtual void GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate);
|
||||
virtual CORSMode GetCORSMode() const;
|
||||
protected:
|
||||
@ -431,11 +432,13 @@ void
|
||||
nsHTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate)
|
||||
{
|
||||
aTitle.Truncate();
|
||||
aType.Truncate();
|
||||
aMedia.Truncate();
|
||||
*aIsScoped = false;
|
||||
*aIsAlternate = false;
|
||||
|
||||
nsAutoString rel;
|
||||
|
@ -86,6 +86,7 @@ protected:
|
||||
void GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate);
|
||||
/**
|
||||
* Common method to call from the various mutation observer methods.
|
||||
@ -298,6 +299,7 @@ void
|
||||
nsHTMLStyleElement::GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate)
|
||||
{
|
||||
aTitle.Truncate();
|
||||
@ -317,6 +319,8 @@ nsHTMLStyleElement::GetStyleSheetInfo(nsAString& aTitle,
|
||||
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType);
|
||||
|
||||
*aIsScoped = HasAttr(kNameSpaceID_None, nsGkAtoms::scoped);
|
||||
|
||||
nsAutoString mimeType;
|
||||
nsAutoString notUsed;
|
||||
nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
|
||||
|
@ -3,6 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/SVGStyleElement.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
@ -274,8 +275,10 @@ void
|
||||
SVGStyleElement::GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate)
|
||||
{
|
||||
*aIsScoped = false;
|
||||
*aIsAlternate = false;
|
||||
|
||||
nsAutoString title;
|
||||
|
@ -97,6 +97,7 @@ protected:
|
||||
void GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate);
|
||||
virtual CORSMode GetCORSMode() const;
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsIDOMLinkStyle.h"
|
||||
#include "nsIDOMStyleSheet.h"
|
||||
#include "nsIDocument.h"
|
||||
@ -17,6 +18,7 @@
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
class nsXMLStylesheetPI : public nsXMLProcessingInstruction,
|
||||
public nsStyleLinkElement
|
||||
@ -57,6 +59,7 @@ protected:
|
||||
void GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate);
|
||||
virtual nsGenericDOMDataNode* CloneDataNode(nsINodeInfo *aNodeInfo,
|
||||
bool aCloneText) const;
|
||||
@ -177,11 +180,13 @@ void
|
||||
nsXMLStylesheetPI::GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate)
|
||||
{
|
||||
aTitle.Truncate();
|
||||
aType.Truncate();
|
||||
aMedia.Truncate();
|
||||
*aIsScoped = false;
|
||||
*aIsAlternate = false;
|
||||
|
||||
// xml-stylesheet PI is special only in prolog
|
||||
|
@ -743,7 +743,7 @@ nsStyleSet::AssertNoCSSRules(nsRuleNode* aCurrLevelNode,
|
||||
// Enumerate the rules in a way that cares about the order of the rules.
|
||||
void
|
||||
nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
RuleProcessorData* aData, nsIContent* aContent,
|
||||
RuleProcessorData* aData, Element* aElement,
|
||||
nsRuleWalker* aRuleWalker)
|
||||
{
|
||||
SAMPLE_LABEL("nsStyleSet", "FileRules");
|
||||
@ -775,7 +775,7 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
|
||||
aRuleWalker->SetLevel(eUserSheet, false, true);
|
||||
bool skipUserStyles =
|
||||
aContent && aContent->IsInNativeAnonymousSubtree();
|
||||
aElement && aElement->IsInNativeAnonymousSubtree();
|
||||
if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different
|
||||
(*aCollectorFunc)(mRuleProcessors[eUserSheet], aData);
|
||||
nsRuleNode* lastUserRN = aRuleWalker->CurrentNode();
|
||||
@ -788,7 +788,7 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
|
||||
aRuleWalker->SetLevel(eDocSheet, false, true);
|
||||
bool cutOffInheritance = false;
|
||||
if (mBindingManager && aContent) {
|
||||
if (mBindingManager && aElement) {
|
||||
// We can supply additional document-level sheets that should be walked.
|
||||
mBindingManager->WalkRules(aCollectorFunc,
|
||||
static_cast<ElementDependentRuleProcessorData*>(aData),
|
||||
|
@ -342,11 +342,11 @@ class nsStyleSet
|
||||
|
||||
// Enumerate the rules in a way that cares about the order of the
|
||||
// rules.
|
||||
// aContent is the node the rules are for. It might be null. aData
|
||||
// aElement is the element the rules are for. It might be null. aData
|
||||
// is the closure to pass to aCollectorFunc. If aContent is not null,
|
||||
// aData must be a RuleProcessorData*
|
||||
void FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
RuleProcessorData* aData, nsIContent* aContent,
|
||||
RuleProcessorData* aData, mozilla::dom::Element* aElement,
|
||||
nsRuleWalker* aRuleWalker);
|
||||
|
||||
// Enumerate all the rules in a way that doesn't care about the order
|
||||
|
Loading…
Reference in New Issue
Block a user