Bug 1331322 - Add a flag to indicate that a node is native anonymous content. r=bz
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -189,17 +189,17 @@ public:
/**
* Makes this content anonymous
* @see nsIAnonymousContentCreator
*/
void SetIsNativeAnonymousRoot()
{
SetFlags(NODE_IS_ANONYMOUS_ROOT | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
- NODE_IS_NATIVE_ANONYMOUS_ROOT);
+ NODE_IS_NATIVE_ANONYMOUS_ROOT | NODE_IS_NATIVE_ANONYMOUS);
}
/**
* Returns |this| if it is not chrome-only/native anonymous, otherwise
* first non chrome-only/native anonymous ancestor.
*/
virtual nsIContent* FindFirstNonChromeOnlyAccessContent() const;
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -122,18 +122,38 @@ enum {
// in the document and therefore should get bindings attached.
NODE_FORCE_XBL_BINDINGS = NODE_FLAG_BIT(5),
// Whether a binding manager may have a pointer to this
NODE_MAY_BE_IN_BINDING_MNGR = NODE_FLAG_BIT(6),
NODE_IS_EDITABLE = NODE_FLAG_BIT(7),
- // Bit that will soon be used for other things.
- THIS_BIT_BELONGS_TO_BHOLLEY = NODE_FLAG_BIT(8),
+ // This node was created by layout as native anonymous content. This
+ // generally corresponds to things created by nsIAnonymousContentCreator,
+ // though there are exceptions (svg:use content does not have this flag
+ // set, and any non-nsIAnonymousContentCreator callers of
+ // SetIsNativeAnonymousRoot also get this flag).
+ //
+ // One very important aspect here is that this node is not transitive over
+ // the subtree (if you want that, use NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE).
+ // If Gecko code somewhere attaches children to a node with this bit set,
+ // the children will not have the bit themselves unless the calling code sets
+ // it explicitly. This means that XBL content bound to NAC doesn't get this
+ // bit, nor do nodes inserted by editor.
+ //
+ // For now, this bit exists primarily to control style inheritance behavior,
+ // since the nodes for which we set it are often used to implement pseudo-
+ // elements, which need to inherit style from a script-visible element.
+ //
+ // A more general principle for this bit might be this: If the node is entirely
+ // a detail of layout, is not script-observable in any way, and other engines
+ // might accomplish the same task with a nodeless layout frame, then the node
+ // should have this bit set.
+ NODE_IS_NATIVE_ANONYMOUS = NODE_FLAG_BIT(8),
// Whether the node participates in a shadow tree.
NODE_IS_IN_SHADOW_TREE = NODE_FLAG_BIT(9),
// Node has an :empty or :-moz-only-whitespace selector
NODE_HAS_EMPTY_SELECTOR = NODE_FLAG_BIT(10),
// A child of the node has a selector such that any insertion,
@@ -1166,16 +1186,25 @@ public:
#ifdef MOZILLA_INTERNAL_API
return IsEditableInternal();
#else
return IsEditableExternal();
#endif
}
/**
+ * Returns true if |this| is native anonymous (i.e. created by
+ * nsIAnonymousContentCreator);
+ */
+ bool IsNativeAnonymous() const
+ {
+ return HasFlag(NODE_IS_NATIVE_ANONYMOUS);
+ }
+
+ /**
* Returns true if |this| or any of its ancestors is native anonymous.
*/
bool IsInNativeAnonymousSubtree() const
{
#ifdef DEBUG
if (HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE)) {
return true;
}
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -4182,16 +4182,23 @@ ConnectAnonymousTreeDescendants(nsIConte
NS_ASSERTION(content, "null anonymous content?");
ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
aParent->AppendChildTo(content, false);
}
}
+void SetNativeAnonymousBitOnDescendants(nsIContent *aRoot)
+{
+ for (nsIContent* curr = aRoot; curr; curr = curr->GetNextNode(aRoot)) {
+ curr->SetFlags(NODE_IS_NATIVE_ANONYMOUS);
+ }
+}
+
nsresult
nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
nsIFrame* aParentFrame,
nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent)
{
nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
if (!creator)
return NS_OK;
@@ -4203,25 +4210,26 @@ nsCSSFrameConstructor::GetAnonymousConte
}
uint32_t count = aContent.Length();
for (uint32_t i=0; i < count; i++) {
// get our child's content and set its parent to our content
nsIContent* content = aContent[i].mContent;
NS_ASSERTION(content, "null anonymous content?");
+ ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
+
// least-surprise CSS binding until we do the SVG specified
// cascading rules for <svg:use> - bug 265894
if (aParentFrame->GetType() == nsGkAtoms::svgUseFrame) {
content->SetFlags(NODE_IS_ANONYMOUS_ROOT);
} else {
content->SetIsNativeAnonymousRoot();
- }
-
- ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
+ SetNativeAnonymousBitOnDescendants(content);
+ }
bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
// If the parent is in a shadow tree, make sure we don't
// bind with a document because shadow roots and its descendants
// are not in document.
nsIDocument* bindDocument =
aParent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;