Bug 476245. Keep better track of our anonymous content. r=smaug, sr=jst

This commit is contained in:
Boris Zbarsky 2009-02-24 13:39:09 -05:00
parent e960f589c6
commit a1f888815b
6 changed files with 70 additions and 28 deletions

View File

@ -151,7 +151,11 @@ public:
*/
PRBool IsRootOfNativeAnonymousSubtree() const
{
return HasFlag(NODE_IS_ANONYMOUS);
NS_ASSERTION(!HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT) ||
(HasFlag(NODE_IS_ANONYMOUS) &&
HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE)),
"Some flags seem to be missing!");
return HasFlag(NODE_IS_NATIVE_ANONYMOUS_ROOT);
}
/**
@ -160,7 +164,8 @@ public:
*/
void SetNativeAnonymous()
{
SetFlags(NODE_IS_ANONYMOUS | NODE_IS_IN_ANONYMOUS_SUBTREE);
SetFlags(NODE_IS_ANONYMOUS | NODE_IS_IN_ANONYMOUS_SUBTREE |
NODE_IS_NATIVE_ANONYMOUS_ROOT);
}
/**
@ -202,8 +207,12 @@ public:
(GetParent() && GetBindingParent() == GetParent()),
"root of native anonymous subtree must have parent equal "
"to binding parent");
nsIContent *bindingParent = GetBindingParent();
return bindingParent && bindingParent == GetParent();
NS_ASSERTION(!GetParent() ||
((GetBindingParent() == GetParent()) ==
HasFlag(NODE_IS_ANONYMOUS)),
"For nodes with parent, flag and GetBindingParent() check "
"should match");
return HasFlag(NODE_IS_ANONYMOUS);
}
/**

View File

@ -77,51 +77,66 @@ enum {
// Whether this node has had any properties set on it
NODE_HAS_PROPERTIES = 0x00000004U,
// Whether this node is anonymous
// Whether this node is the root of an anonymous subtree. Note that this
// need not be a native anonymous subtree. Any anonymous subtree, including
// XBL-generated ones, will do. This flag is set-once: once a node has it,
// it must not be removed.
// NOTE: Should only be used on nsIContent nodes
NODE_IS_ANONYMOUS = 0x00000008U,
// Whether the node has some ancestor, possibly itself, that is native
// anonymous. This includes ancestors crossing XBL scopes, in cases when an
// XBL binding is attached to an element which has a native anonymous
// ancestor. This flag is set-once: once a node has it, it must not be
// removed.
// NOTE: Should only be used on nsIContent nodes
NODE_IS_IN_ANONYMOUS_SUBTREE = 0x00000010U,
// Whether this node is the root of a native anonymous (from the perspective
// of its parent) subtree. This flag is set-once: once a node has it, it
// must not be removed.
// NOTE: Should only be used on nsIContent nodes
NODE_IS_NATIVE_ANONYMOUS_ROOT = 0x00000020U,
// Whether this node may have a frame
// NOTE: Should only be used on nsIContent nodes
NODE_MAY_HAVE_FRAME = 0x00000020U,
NODE_MAY_HAVE_FRAME = 0x00000040U,
// Forces the XBL code to treat this node as if it were
// in the document and therefore should get bindings attached.
NODE_FORCE_XBL_BINDINGS = 0x00000040U,
NODE_FORCE_XBL_BINDINGS = 0x00000080U,
// Whether a binding manager may have a pointer to this
NODE_MAY_BE_IN_BINDING_MNGR = 0x00000080U,
NODE_MAY_BE_IN_BINDING_MNGR = 0x00000100U,
NODE_IS_EDITABLE = 0x00000100U,
NODE_IS_EDITABLE = 0x00000200U,
// Optimizations to quickly check whether element may have ID, class or style
// attributes. Not all element implementations may use these!
NODE_MAY_HAVE_ID = 0x00000200U,
NODE_MAY_HAVE_ID = 0x00000400U,
// For all Element nodes, NODE_MAY_HAVE_CLASS is guaranteed to be set if the
// node in fact has a class, but may be set even if it doesn't.
NODE_MAY_HAVE_CLASS = 0x00000400U,
NODE_MAY_HAVE_STYLE = 0x00000800U,
NODE_MAY_HAVE_CLASS = 0x00000800U,
NODE_MAY_HAVE_STYLE = 0x00001000U,
NODE_IS_INSERTION_PARENT = 0x00001000U,
NODE_IS_INSERTION_PARENT = 0x00002000U,
// Node has an :empty or :-moz-only-whitespace selector
NODE_HAS_EMPTY_SELECTOR = 0x00002000U,
NODE_HAS_EMPTY_SELECTOR = 0x00004000U,
// A child of the node has a selector such that any insertion,
// removal, or appending of children requires restyling the parent.
NODE_HAS_SLOW_SELECTOR = 0x00004000U,
NODE_HAS_SLOW_SELECTOR = 0x00008000U,
// A child of the node has a :first-child, :-moz-first-node,
// :only-child, :last-child or :-moz-last-node selector.
NODE_HAS_EDGE_CHILD_SELECTOR = 0x00008000U,
NODE_HAS_EDGE_CHILD_SELECTOR = 0x00010000U,
// A child of the node has a selector such that any insertion or
// removal of children requires restyling the parent (but append is
// OK).
NODE_HAS_SLOW_SELECTOR_NOAPPEND
= 0x00010000U,
= 0x00020000U,
NODE_ALL_SELECTOR_FLAGS = NODE_HAS_EMPTY_SELECTOR |
NODE_HAS_SLOW_SELECTOR |
@ -129,7 +144,7 @@ enum {
NODE_HAS_SLOW_SELECTOR_NOAPPEND,
// Four bits for the script-type ID
NODE_SCRIPT_TYPE_OFFSET = 17,
NODE_SCRIPT_TYPE_OFFSET = 18,
NODE_SCRIPT_TYPE_SIZE = 4,
@ -154,8 +169,8 @@ inline nsINode* NODE_FROM(C& aContent, D& aDocument)
// IID for the nsINode interface
#define NS_INODE_IID \
{ 0x075803c5, 0xb37f, 0x489f, \
{ 0x9b, 0x17, 0x9a, 0x60, 0x44, 0x5d, 0x66, 0x1b } }
{ 0x7bccc9bd, 0x30eb, 0x47c0, \
{ 0x8b, 0xc7, 0x6f, 0x19, 0x75, 0xc8, 0xe7, 0xd7 } }
/**
* An internal interface that abstracts some DOMNode-related parts that both
@ -643,7 +658,10 @@ public:
void SetFlags(PtrBits aFlagsToSet)
{
NS_ASSERTION(!(aFlagsToSet & (NODE_IS_ANONYMOUS | NODE_MAY_HAVE_FRAME)) ||
NS_ASSERTION(!(aFlagsToSet & (NODE_IS_ANONYMOUS |
NODE_MAY_HAVE_FRAME |
NODE_IS_NATIVE_ANONYMOUS_ROOT |
NODE_IS_IN_ANONYMOUS_SUBTREE)) ||
IsNodeOfType(eCONTENT),
"Flag only permitted on nsIContent nodes");
PtrBits* flags = HasSlots() ? &FlagsAsSlots()->mFlags :
@ -653,6 +671,11 @@ public:
void UnsetFlags(PtrBits aFlagsToUnset)
{
NS_ASSERTION(!(aFlagsToUnset &
(NODE_IS_ANONYMOUS |
NODE_IS_IN_ANONYMOUS_SUBTREE |
NODE_IS_NATIVE_ANONYMOUS_ROOT)),
"Trying to unset write-only flags");
PtrBits* flags = HasSlots() ? &FlagsAsSlots()->mFlags :
&mFlagsOrSlots;
*flags &= ~aFlagsToUnset;

View File

@ -545,8 +545,7 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
"Trying to re-bind content from native anonymous subtree to "
"non-native anonymous parent!");
slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
if (IsRootOfNativeAnonymousSubtree() ||
aParent->IsInNativeAnonymousSubtree()) {
if (aParent->IsInNativeAnonymousSubtree()) {
SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
}
}

View File

@ -2545,8 +2545,7 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
(aParent && aParent->IsInNativeAnonymousSubtree()),
"Trying to re-bind content from native anonymous subtree to "
"non-native anonymous parent!");
if (IsRootOfNativeAnonymousSubtree() ||
aParent && aParent->IsInNativeAnonymousSubtree()) {
if (aParent && aParent->IsInNativeAnonymousSubtree()) {
SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
}
@ -3893,6 +3892,13 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
else {
// Not inserting a fragment but rather a single node.
if (newContent->IsRootOfAnonymousSubtree()) {
// This is anonymous content. Don't allow its insertion
// anywhere, since it might have UnbindFromTree calls coming
// its way.
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
// Remove the element from the old parent if one exists
nsINode* oldParent = newContent->GetNodeParent();
@ -3901,6 +3907,7 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
if (removeIndex < 0) {
// newContent is anonymous. We can't deal with this, so just bail
NS_ERROR("How come our flags didn't catch this?");
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}

View File

@ -368,6 +368,8 @@ nsXBLBinding::InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElem
return;
}
child->SetFlags(NODE_IS_ANONYMOUS);
#ifdef MOZ_XUL
// To make XUL templates work (and other goodies that happen when
// an element is added to a XUL document), we need to notify the

View File

@ -5393,8 +5393,10 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
#ifdef MOZ_SVG
// least-surprise CSS binding until we do the SVG specified
// cascading rules for <svg:use> - bug 265894
if (!aParent ||
!aParent->NodeInfo()->Equals(nsGkAtoms::use, kNameSpaceID_SVG))
if (aParent &&
aParent->NodeInfo()->Equals(nsGkAtoms::use, kNameSpaceID_SVG)) {
content->SetFlags(NODE_IS_ANONYMOUS);
} else
#endif
{
content->SetNativeAnonymous();