Bug 542592 - Change how we use/store nsDocument::mLinkMap

This makes changes nsDocument::mLinkMap in a number of ways:
1) renamed to mStyledLinks to better reflect its new nature.
2) change it to an nsTHashtable of Link*.  It no longer has a strong reference
3) add some assertions to make sure we call ForgetLink and AddStyleRelevantLink
   in pairs.
This also makes mozilla::dom::Link::ResetLinkState take a boolean indicating if
we should notify or not.
r=bz
This commit is contained in:
Shawn Wilsher 2010-02-24 08:37:03 -08:00
parent 17cfa3d578
commit 149f5aac0a
13 changed files with 112 additions and 434 deletions

View File

@ -72,8 +72,8 @@ enum nsLinkState {
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
{ 0xe88a767e, 0x1ca1, 0x4855, \
{ 0xa7, 0xa4, 0x37, 0x9f, 0x07, 0x89, 0x45, 0xef } }
{ 0xc19d6f16, 0xab13, 0x4dde, \
{ 0x99, 0x7a, 0x51, 0x04, 0xc3, 0x64, 0xd2, 0x51 } }
/**
* A node of content in a document's content model. This interface
@ -668,17 +668,6 @@ public:
*/
virtual PRBool IsLink(nsIURI** aURI) const = 0;
/**
* If the implementing element is a link, calling this method forces it to
* clear its cached href, if it has one.
*
* This function does not notify the document that it may need to restyle the
* link.
*/
virtual void DropCachedHref()
{
}
/**
* Get the cached state of the link. If the state is unknown,
* return eLinkState_Unknown.
@ -690,17 +679,6 @@ public:
return eLinkState_NotLink;
}
/**
* Set the cached state of the link.
*
* @param aState The cached link state of the link.
*/
virtual void SetLinkState(nsLinkState aState)
{
NS_ASSERTION(aState == eLinkState_NotLink,
"Need to override SetLinkState?");
}
/**
* Get a pointer to the full href URI (fully resolved and canonicalized,
* since it's an nsIURI object) for link elements.

View File

@ -104,10 +104,16 @@ struct JSObject;
class nsFrameLoader;
class nsIBoxObject;
namespace mozilla {
namespace dom {
class Link;
} // namespace dom
} // namespace mozilla
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0x7d1ff787, 0x8c35, 0x45f3, \
{ 0xa6, 0x7c, 0x8d, 0x7f, 0x36, 0xbd, 0x4e, 0x68 } }
{ 0xd7978655, 0x9b7d, 0x41e6, \
{ 0xad, 0x48, 0xdf, 0x32, 0x0b, 0x06, 0xb4, 0xda } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -907,17 +913,16 @@ public:
* style.
*/
/**
* Notification that an element is a link with a given URI that is
* relevant to style.
* Notification that an element is a link that is relevant to style.
*/
virtual void AddStyleRelevantLink(nsIContent* aContent, nsIURI* aURI) = 0;
virtual void AddStyleRelevantLink(mozilla::dom::Link* aLink) = 0;
/**
* Notification that an element is a link and its URI might have been
* changed or the element removed. If the element is still a link relevant
* to style, then someone must ensure that AddStyleRelevantLink is
* (eventually) called on it again.
*/
virtual void ForgetLink(nsIContent* aContent) = 0;
virtual void ForgetLink(mozilla::dom::Link* aLink) = 0;
/**
* Resets and removes a box object from the document's box object cache

View File

@ -78,14 +78,6 @@ Link::GetLinkState() const
void
Link::SetLinkState(nsLinkState aState)
{
// Other code may try to reset our state by passing in eLinkState_Unknown. In
// these situations, we want to call ResetLinkState and return since we may
// not be registered, and we may already be in an unknown state.
if (aState == eLinkState_Unknown) {
ResetLinkState();
return;
}
NS_ASSERTION(mRegistered,
"Setting the link state of an unregistered Link!");
NS_ASSERTION(mLinkState != aState,
@ -147,7 +139,7 @@ Link::LinkState() const
// And make sure we are in the document's link map.
nsIDocument *doc = content->GetCurrentDoc();
if (doc) {
doc->AddStyleRelevantLink(content, hrefURI);
doc->AddStyleRelevantLink(self);
}
}
}
@ -470,16 +462,25 @@ Link::GetHash(nsAString &_hash)
}
void
Link::ResetLinkState()
Link::ResetLinkState(bool aNotify)
{
// If we are in our default state, bail early.
if (mLinkState == defaultState) {
return;
}
// If we are not a link, revert to the default state and do no more work.
if (mLinkState == eLinkState_NotLink) {
mLinkState = defaultState;
return;
}
nsIContent *content = Content();
// Tell the document to forget about this link, but only if we are registered.
if (mRegistered) {
nsIDocument *doc = content->GetCurrentDoc();
if (doc) {
doc->ForgetLink(content);
}
// Tell the document to forget about this link.
nsIDocument *doc = content->GetCurrentDoc();
if (doc) {
doc->ForgetLink(this);
}
UnregisterFromHistory();
@ -489,6 +490,17 @@ Link::ResetLinkState()
// Get rid of our cached URI.
mCachedURI = nsnull;
// If aNotify is true, notify both of the visited-related states. We have
// to do that, because we might be racing with a response from history and
// hence need to make sure that we get restyled whether we were visited or
// not before. In particular, we need to make sure that our LinkState() is
// called so that we'll start a new history query as needed.
if (aNotify && doc) {
PRUint32 changedState = NS_EVENT_STATE_VISITED ^ NS_EVENT_STATE_UNVISITED;
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, aNotify);
doc->ContentStatesChanged(content, nsnull, changedState);
}
}
void

View File

@ -87,12 +87,16 @@ public:
nsresult GetPort(nsAString &_port);
nsresult GetHash(nsAString &_hash);
protected:
/**
* Invalidates any link caching, and resets the state to the default.
*
* @param aNotify
* true if ResetLinkState should notify the owning document about style
* changes or false if it should not.
*/
virtual void ResetLinkState();
virtual void ResetLinkState(bool aNotify);
protected:
virtual ~Link();
private:

View File

@ -189,6 +189,10 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
// FOR CSP (autogenerated by xpidl)
#include "nsIContentSecurityPolicy.h"
#include "mozilla/dom/Link.h"
using namespace mozilla::dom;
/* Keeps track of whether or not CSP is enabled */
static PRBool gCSPEnabled = PR_TRUE;
@ -197,122 +201,6 @@ static PRLogModuleInfo* gDocumentLeakPRLog;
static PRLogModuleInfo* gCspPRLog;
#endif
void
nsUint32ToContentHashEntry::Destroy()
{
HashSet* set = GetHashSet();
if (set) {
delete set;
} else {
nsIContent* content = GetContent();
NS_IF_RELEASE(content);
}
}
nsresult
nsUint32ToContentHashEntry::PutContent(nsIContent* aVal)
{
// Add the value to the hash if it is there
HashSet* set = GetHashSet();
if (set) {
nsISupportsHashKey* entry = set->PutEntry(aVal);
return entry ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
// If an element is already there, create a hashtable and both of these to it
nsIContent* oldVal = GetContent();
if (oldVal) {
nsresult rv = InitHashSet(&set);
NS_ENSURE_SUCCESS(rv, rv);
nsISupportsHashKey* entry = set->PutEntry(oldVal);
if (!entry) {
// OOM - we can't insert aVal, but we can at least put oldVal back (even
// if we didn't, we'd still have to release oldVal so that we don't leak)
delete set;
SetContent(oldVal);
// SetContent adds another reference, so release the one we had
NS_RELEASE(oldVal);
return NS_ERROR_OUT_OF_MEMORY;
}
// The hashset adds its own reference, so release the one we had
NS_RELEASE(oldVal);
entry = set->PutEntry(aVal);
return entry ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
// Nothing exists in the hash right now, so just set the single pointer
return SetContent(aVal);
}
void
nsUint32ToContentHashEntry::RemoveContent(nsIContent* aVal)
{
// Remove from the hash if the hash is there
HashSet* set = GetHashSet();
if (set) {
set->RemoveEntry(aVal);
if (set->Count() == 0) {
delete set;
mValOrHash = nsnull;
}
return;
}
// Remove the ptr if there is just a ptr
nsIContent* v = GetContent();
if (v == aVal) {
NS_IF_RELEASE(v);
mValOrHash = nsnull;
}
}
nsresult
nsUint32ToContentHashEntry::InitHashSet(HashSet** aSet)
{
HashSet* newSet = new HashSet();
if (!newSet) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = newSet->Init();
NS_ENSURE_SUCCESS(rv, rv);
mValOrHash = newSet;
*aSet = newSet;
return NS_OK;
}
static PLDHashOperator
nsUint32ToContentHashEntryVisitorCallback(nsISupportsHashKey* aEntry,
void* aClosure)
{
nsUint32ToContentHashEntry::Visitor* visitor =
static_cast<nsUint32ToContentHashEntry::Visitor*>(aClosure);
visitor->Visit(static_cast<nsIContent*>(aEntry->GetKey()));
return PL_DHASH_NEXT;
}
void
nsUint32ToContentHashEntry::VisitContent(Visitor* aVisitor)
{
HashSet* set = GetHashSet();
if (set) {
set->EnumerateEntries(nsUint32ToContentHashEntryVisitorCallback, aVisitor);
if (set->Count() == 0) {
delete set;
mValOrHash = nsnull;
}
return;
}
nsIContent* v = GetContent();
if (v) {
aVisitor->Visit(v);
}
}
#define NAME_NOT_VALID ((nsBaseContentList*)1)
nsIdentifierMapEntry::~nsIdentifierMapEntry()
@ -1716,26 +1604,6 @@ BoxObjectTraverser(const void* key, nsPIBoxObject* boxObject, void* userArg)
return PL_DHASH_NEXT;
}
class LinkMapTraversalVisitor : public nsUint32ToContentHashEntry::Visitor
{
public:
nsCycleCollectionTraversalCallback *mCb;
virtual void Visit(nsIContent* aContent)
{
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*mCb, "mLinkMap entry");
mCb->NoteXPCOMChild(aContent);
}
};
static PLDHashOperator
LinkMapTraverser(nsUint32ToContentHashEntry* aEntry, void* userArg)
{
LinkMapTraversalVisitor visitor;
visitor.mCb = static_cast<nsCycleCollectionTraversalCallback*>(userArg);
aEntry->VisitContent(&visitor);
return PL_DHASH_NEXT;
}
static PLDHashOperator
IdentifierMapEntryTraverse(nsIdentifierMapEntry *aEntry, void *aArg)
{
@ -1800,12 +1668,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDOMImplementation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOriginalDocument)
// An element will only be in the linkmap as long as it's in the
// document, so we'll traverse the table here instead of from the element.
if (tmp->mLinkMap.IsInitialized()) {
tmp->mLinkMap.EnumerateEntries(LinkMapTraverser, &cb);
}
// Traverse all our nsCOMArrays.
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mStyleSheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCatalogSheets)
@ -1830,11 +1692,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
// Tear down linkmap. This is a performance optimization so that we
// don't waste time removing links one by one as they are removed
// from the doc.
tmp->DestroyLinkMap();
// Clear out our external resources
tmp->mExternalResourceMap.Shutdown();
@ -1876,7 +1733,7 @@ nsDocument::Init()
}
mIdentifierMap.Init();
mLinkMap.Init();
(void)mStyledLinks.Init();
mRadioGroups.Init();
// Force initialization.
@ -7488,107 +7345,60 @@ static PRUint32 GetURIHash(nsIURI* aURI)
}
void
nsDocument::AddStyleRelevantLink(nsIContent* aContent, nsIURI* aURI)
nsDocument::AddStyleRelevantLink(Link* aLink)
{
nsUint32ToContentHashEntry* entry = mLinkMap.PutEntry(GetURIHash(aURI));
if (!entry) // out of memory?
return;
entry->PutContent(aContent);
NS_ASSERTION(aLink, "Passing in a null link. Expect crashes RSN!");
#ifdef DEBUG
nsPtrHashKey<Link>* entry = mStyledLinks.GetEntry(aLink);
NS_ASSERTION(!entry, "Document already knows about this Link!");
mStyledLinksCleared = false;
#endif
(void)mStyledLinks.PutEntry(aLink);
}
void
nsDocument::ForgetLink(nsIContent* aContent)
nsDocument::ForgetLink(Link* aLink)
{
// Important optimization! If the link map is empty (as it will be
// during teardown because we destroy the map early), then stop
// now before we waste time constructing a URI object.
if (mLinkMap.Count() == 0)
return;
nsCOMPtr<nsIURI> uri;
if (!aContent->IsLink(getter_AddRefs(uri)))
return;
PRUint32 hash = GetURIHash(uri);
nsUint32ToContentHashEntry* entry = mLinkMap.GetEntry(hash);
if (!entry)
return;
entry->RemoveContent(aContent);
if (entry->IsEmpty()) {
// Remove the entry and allow the table to resize, in case
// a lot of links are being removed from the document or modified
mLinkMap.RemoveEntry(hash);
}
NS_ASSERTION(aLink, "Passing in a null link. Expect crashes RSN!");
#ifdef DEBUG
nsPtrHashKey<Link>* entry = mStyledLinks.GetEntry(aLink);
NS_ASSERTION(entry || mStyledLinksCleared,
"Document knows nothing about this Link!");
#endif
(void)mStyledLinks.RemoveEntry(aLink);
}
void
nsDocument::DestroyLinkMap()
{
mLinkMap.Clear();
#ifdef DEBUG
mStyledLinksCleared = true;
#endif
mStyledLinks.Clear();
}
class RefreshLinkStateVisitor : public nsUint32ToContentHashEntry::Visitor
static
PLDHashOperator
EnumerateStyledLinks(nsPtrHashKey<Link>* aEntry, void* aArray)
{
public:
nsCOMArray<nsIContent> contentVisited;
virtual void Visit(nsIContent* aContent) {
// We can't call ContentStatesChanged here, because that may modify the link
// map. Instead, we just add to an array and call ContentStatesChanged
// later.
aContent->SetLinkState(eLinkState_Unknown);
contentVisited.AppendObject(aContent);
}
};
static PLDHashOperator
RefreshLinkStateTraverser(nsUint32ToContentHashEntry* aEntry,
void* userArg)
{
RefreshLinkStateVisitor *visitor =
static_cast<RefreshLinkStateVisitor*>(userArg);
aEntry->VisitContent(visitor);
nsTArray<Link*>* array = static_cast<nsTArray<Link*>*>(aArray);
(void)array->AppendElement(aEntry->GetKey());
return PL_DHASH_NEXT;
}
// Helper function for nsDocument::RefreshLinkHrefs
static void
DropCachedHrefsRecursive(nsIContent * const elem)
{
// Drop the element's cached href, if it has one. (If it doesn't have
// one, this call does nothing.) We could check first that elem is an <a>
// tag to avoid making a virtual call, but it turns out not to make a
// substantial perf difference either way. This doesn't restyle the link,
// but we do that later.
elem->DropCachedHref();
PRUint32 childCount;
nsIContent * const * child = elem->GetChildArray(&childCount);
nsIContent * const * end = child + childCount;
for ( ; child != end; ++child) {
DropCachedHrefsRecursive(*child);
}
}
void
nsDocument::RefreshLinkHrefs()
{
if (!GetRootContent())
return;
// First, walk the DOM and clear the cached hrefs of all the <a> tags.
DropCachedHrefsRecursive(GetRootContent());
// Now update the styles of everything in the linkmap.
RefreshLinkStateVisitor visitor;
mLinkMap.EnumerateEntries(RefreshLinkStateTraverser, &visitor);
// Get a list of all links we know about. We will reset them, which will
// remove them from the document, so we need a copy of what is in the
// hashtable.
nsTArray<Link*> linksToNotify(mStyledLinks.Count());
(void)mStyledLinks.EnumerateEntries(EnumerateStyledLinks, &linksToNotify);
// Reset all of our styled links.
MOZ_AUTO_DOC_UPDATE(this, UPDATE_CONTENT_STATE, PR_TRUE);
for (PRUint32 count = visitor.contentVisited.Count(), i = 0; i < count; i++) {
ContentStatesChanged(visitor.contentVisited[i],
nsnull, NS_EVENT_STATE_VISITED);
for (nsTArray_base::size_type i = 0; i < linksToNotify.Length(); i++) {
linksToNotify[i]->ResetLinkState(true);
}
}

View File

@ -140,83 +140,6 @@ class nsChildContentList;
class nsSMILAnimationController;
#endif // MOZ_SMIL
/**
* Hashentry using a PRUint32 key and a cheap set of nsIContent* owning
* pointers for the value.
*
* @see nsTHashtable::EntryType for specification
*/
class nsUint32ToContentHashEntry : public PLDHashEntryHdr
{
public:
typedef const PRUint32& KeyType;
typedef const PRUint32* KeyTypePointer;
nsUint32ToContentHashEntry(const KeyTypePointer key) :
mValue(*key), mValOrHash(nsnull) { }
nsUint32ToContentHashEntry(const nsUint32ToContentHashEntry& toCopy) :
mValue(toCopy.mValue), mValOrHash(toCopy.mValOrHash)
{
// Pathetic attempt to not die: clear out the other mValOrHash so we're
// effectively stealing it. If toCopy is destroyed right after this,
// we'll be OK.
const_cast<nsUint32ToContentHashEntry&>(toCopy).mValOrHash = nsnull;
NS_ERROR("Copying not supported. Fasten your seat belt.");
}
~nsUint32ToContentHashEntry() { Destroy(); }
KeyType GetKey() const { return mValue; }
PRBool KeyEquals(KeyTypePointer aKey) const { return mValue == *aKey; }
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey) { return *aKey; }
enum { ALLOW_MEMMOVE = PR_TRUE };
// Content set methods
nsresult PutContent(nsIContent* aContent);
void RemoveContent(nsIContent* aContent);
struct Visitor {
virtual void Visit(nsIContent* aContent) = 0;
};
void VisitContent(Visitor* aVisitor);
PRBool IsEmpty() { return mValOrHash == nsnull; }
private:
typedef PRUptrdiff PtrBits;
typedef nsTHashtable<nsISupportsHashKey> HashSet;
/** Get the hash pointer (or null if we're not a hash) */
HashSet* GetHashSet()
{
return (PtrBits(mValOrHash) & 0x1) ? nsnull : (HashSet*)mValOrHash;
}
/** Find out whether it is an nsIContent (returns weak) */
nsIContent* GetContent()
{
return (PtrBits(mValOrHash) & 0x1)
? (nsIContent*)(PtrBits(mValOrHash) & ~0x1)
: nsnull;
}
/** Set the single element, adding a reference */
nsresult SetContent(nsIContent* aVal)
{
NS_IF_ADDREF(aVal);
mValOrHash = (void*)(PtrBits(aVal) | 0x1);
return NS_OK;
}
/** Initialize the hash */
nsresult InitHashSet(HashSet** aSet);
void Destroy();
private:
const PRUint32 mValue;
/** A hash or nsIContent ptr, depending on the lower bit (0=hash, 1=ptr) */
void* mValOrHash;
};
/**
* Right now our identifier map entries contain information for 'name'
@ -943,8 +866,8 @@ public:
virtual NS_HIDDEN_(void) BlockOnload();
virtual NS_HIDDEN_(void) UnblockOnload(PRBool aFireSync);
virtual NS_HIDDEN_(void) AddStyleRelevantLink(nsIContent* aContent, nsIURI* aURI);
virtual NS_HIDDEN_(void) ForgetLink(nsIContent* aContent);
virtual NS_HIDDEN_(void) AddStyleRelevantLink(mozilla::dom::Link* aLink);
virtual NS_HIDDEN_(void) ForgetLink(mozilla::dom::Link* aLink);
NS_HIDDEN_(void) ClearBoxObjectFor(nsIContent* aContent);
NS_IMETHOD GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult);
@ -1242,8 +1165,14 @@ private:
nsCOMPtr<nsIRequest> mOnloadBlocker;
ReadyState mReadyState;
// A map from unvisited URI hashes to content elements
nsTHashtable<nsUint32ToContentHashEntry> mLinkMap;
// A hashtable of styled links keyed by address pointer.
nsTHashtable<nsPtrHashKey<mozilla::dom::Link> > mStyledLinks;
#ifdef DEBUG
// Indicates whether mStyledLinks was cleared or not. This is used to track
// state so we can provide useful assertions to consumers of ForgetLink and
// AddStyleRelevantLink.
bool mStyledLinksCleared;
#endif
// Member to store out last-selected stylesheet set.
nsString mLastStyleSheetSet;

View File

@ -2646,10 +2646,6 @@ nsGenericElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
// anonymous content that the document is changing.
document->BindingManager()->ChangeDocumentFor(this, document, nsnull);
if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
document->ForgetLink(this);
}
document->ClearBoxObjectFor(this);
}
@ -4299,20 +4295,6 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
"Don't call SetAttr with unknown namespace");
nsIDocument* doc = GetCurrentDoc();
if (kNameSpaceID_XLink == aNamespaceID && nsGkAtoms::href == aName) {
// XLink URI(s) might be changing. Drop the link from the map. If it
// is still style relevant it will be re-added by
// nsStyleUtil::IsLink. Make sure to keep the style system
// consistent so this remains true! In particular if the style system
// were to get smarter and not restyling an XLink element if the href
// doesn't change in a "significant" way, we'd need to do the same
// significance check here.
if (doc) {
doc->ForgetLink(this);
}
}
nsAutoString oldValue;
PRBool modification = PR_FALSE;
PRBool hasListeners = aNotify &&
@ -4629,12 +4611,6 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIDOMMutationEvent::REMOVAL);
}
if (document && kNameSpaceID_XLink == aNameSpaceID &&
nsGkAtoms::href == aName) {
// XLink URI might be changing.
document->ForgetLink(this);
}
// When notifying, make sure to keep track of states whose value
// depends solely on the value of an attribute.
PRUint32 stateMask;

View File

@ -111,7 +111,6 @@ public:
virtual PRBool IsLink(nsIURI** aURI) const;
virtual void GetLinkTarget(nsAString& aTarget);
virtual nsLinkState GetLinkState() const;
virtual void SetLinkState(nsLinkState aState);
virtual already_AddRefed<nsIURI> GetHrefURI() const;
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
@ -131,8 +130,6 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual void DropCachedHref();
virtual PRInt32 IntrinsicState() const;
};
@ -200,7 +197,7 @@ nsHTMLAnchorElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
Link::ResetLinkState();
Link::ResetLinkState(false);
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
@ -223,7 +220,7 @@ nsHTMLAnchorElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
// If this link is ever reinserted into a document, it might
// be under a different xml:base, so forget the cached state now.
Link::ResetLinkState();
Link::ResetLinkState(false);
if (IsInDoc()) {
RegUnRegAccessKey(PR_FALSE);
@ -422,12 +419,6 @@ nsHTMLAnchorElement::GetLinkState() const
return Link::GetLinkState();
}
void
nsHTMLAnchorElement::SetLinkState(nsLinkState aState)
{
Link::SetLinkState(aState);
}
already_AddRefed<nsIURI>
nsHTMLAnchorElement::GetHrefURI() const
{
@ -443,7 +434,7 @@ nsHTMLAnchorElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsAutoString val;
GetHref(val);
if (!val.Equals(aValue)) {
Link::ResetLinkState();
Link::ResetLinkState(!!aNotify);
}
}
@ -467,7 +458,7 @@ nsHTMLAnchorElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify)
{
if (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
Link::ResetLinkState();
Link::ResetLinkState(!!aNotify);
}
if (aAttribute == nsGkAtoms::accesskey &&
@ -488,12 +479,6 @@ nsHTMLAnchorElement::ParseAttribute(PRInt32 aNamespaceID,
aResult);
}
void
nsHTMLAnchorElement::DropCachedHref()
{
Link::ResetLinkState();
}
PRInt32
nsHTMLAnchorElement::IntrinsicState() const
{

View File

@ -93,7 +93,6 @@ public:
virtual PRBool IsLink(nsIURI** aURI) const;
virtual void GetLinkTarget(nsAString& aTarget);
virtual nsLinkState GetLinkState() const;
virtual void SetLinkState(nsLinkState aState);
virtual already_AddRefed<nsIURI> GetHrefURI() const;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
@ -206,7 +205,7 @@ nsHTMLAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
Link::ResetLinkState();
Link::ResetLinkState(false);
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
@ -225,7 +224,7 @@ nsHTMLAreaElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
// If this link is ever reinserted into a document, it might
// be under a different xml:base, so forget the cached state now.
Link::ResetLinkState();
Link::ResetLinkState(false);
if (IsInDoc()) {
RegUnRegAccessKey(PR_FALSE);
@ -244,7 +243,7 @@ nsHTMLAreaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
}
if (aName == nsGkAtoms::href && aNameSpaceID == kNameSpaceID_None) {
Link::ResetLinkState();
Link::ResetLinkState(!!aNotify);
}
nsresult rv =
@ -263,7 +262,7 @@ nsHTMLAreaElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify)
{
if (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
Link::ResetLinkState();
Link::ResetLinkState(!!aNotify);
}
if (aAttribute == nsGkAtoms::accesskey &&
@ -320,12 +319,6 @@ nsHTMLAreaElement::GetLinkState() const
return Link::GetLinkState();
}
void
nsHTMLAreaElement::SetLinkState(nsLinkState aState)
{
Link::SetLinkState(aState);
}
already_AddRefed<nsIURI>
nsHTMLAreaElement::GetHrefURI() const
{

View File

@ -114,7 +114,6 @@ public:
virtual PRBool IsLink(nsIURI** aURI) const;
virtual void GetLinkTarget(nsAString& aTarget);
virtual nsLinkState GetLinkState() const;
virtual void SetLinkState(nsLinkState aState);
virtual already_AddRefed<nsIURI> GetHrefURI() const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
@ -205,7 +204,7 @@ nsHTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
Link::ResetLinkState();
Link::ResetLinkState(false);
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
@ -240,7 +239,7 @@ nsHTMLLinkElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
// If this link is ever reinserted into a document, it might
// be under a different xml:base, so forget the cached state now.
Link::ResetLinkState();
Link::ResetLinkState(false);
// Once we have XPCOMGC we shouldn't need to call UnbindFromTree during Unlink
// and so this messy event dispatch can go away.
@ -286,7 +285,7 @@ nsHTMLLinkElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
PRBool aNotify)
{
if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
Link::ResetLinkState();
Link::ResetLinkState(!!aNotify);
}
nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
@ -316,7 +315,7 @@ nsHTMLLinkElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify)
{
if (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
Link::ResetLinkState();
Link::ResetLinkState(!!aNotify);
}
nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute,
@ -366,12 +365,6 @@ nsHTMLLinkElement::GetLinkState() const
return Link::GetLinkState();
}
void
nsHTMLLinkElement::SetLinkState(nsLinkState aState)
{
Link::SetLinkState(aState);
}
already_AddRefed<nsIURI>
nsHTMLLinkElement::GetHrefURI() const
{

View File

@ -126,7 +126,7 @@ nsSVGAElement::BindToTree(nsIDocument *aDocument, nsIContent *aParent,
nsIContent *aBindingParent,
PRBool aCompileEventHandlers)
{
Link::ResetLinkState();
Link::ResetLinkState(false);
nsresult rv = nsSVGAElementBase::BindToTree(aDocument, aParent,
aBindingParent,
@ -141,7 +141,7 @@ nsSVGAElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
// If this link is ever reinserted into a document, it might
// be under a different xml:base, so forget the cached state now.
Link::ResetLinkState();
Link::ResetLinkState(false);
nsSVGAElementBase::UnbindFromTree(aDeep, aNullParent);
}
@ -152,12 +152,6 @@ nsSVGAElement::GetLinkState() const
return Link::GetLinkState();
}
void
nsSVGAElement::SetLinkState(nsLinkState aState)
{
Link::SetLinkState(aState);
}
already_AddRefed<nsIURI>
nsSVGAElement::GetHrefURI() const
{
@ -269,7 +263,7 @@ nsSVGAElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
PRBool aNotify)
{
if (aName == nsGkAtoms::href && aNameSpaceID == kNameSpaceID_XLink) {
Link::ResetLinkState();
Link::ResetLinkState(!!aNotify);
}
return nsSVGAElementBase::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
@ -281,7 +275,7 @@ nsSVGAElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttr,
PRBool aNotify)
{
if (aAttr == nsGkAtoms::href && aNameSpaceID == kNameSpaceID_XLink) {
Link::ResetLinkState();
Link::ResetLinkState(!!aNotify);
}
return nsSVGAElementBase::UnsetAttr(aNameSpaceID, aAttr, aNotify);

View File

@ -87,7 +87,6 @@ public:
virtual PRBool IsLink(nsIURI** aURI) const;
virtual void GetLinkTarget(nsAString& aTarget);
virtual nsLinkState GetLinkState() const;
virtual void SetLinkState(nsLinkState aState);
virtual already_AddRefed<nsIURI> GetHrefURI() const;
virtual PRInt32 IntrinsicState() const;
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,

View File

@ -112,7 +112,7 @@ Link::SetLinkState(nsLinkState aState)
}
void
Link::ResetLinkState()
Link::ResetLinkState(bool aNotify)
{
NS_NOTREACHED("Unexpected call to Link::ResetLinkState");
}