зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 06b691e8cbcd
This commit is contained in:
Родитель
a37874c892
Коммит
291a108475
|
@ -51,6 +51,7 @@
|
|||
#include "nsTPtrArray.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIURI.h"
|
||||
#include "prprf.h"
|
||||
#ifdef MOZ_SVG
|
||||
#include "nsISVGValue.h"
|
||||
|
@ -259,6 +260,11 @@ nsAttrValue::SetTo(const nsAttrValue& aOther)
|
|||
cont->mFloatValue = otherCont->mFloatValue;
|
||||
break;
|
||||
}
|
||||
case eLazyURIValue:
|
||||
{
|
||||
NS_IF_ADDREF(cont->mURI = otherCont->mURI);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
NS_NOTREACHED("unknown type stored in MiscContainer");
|
||||
|
@ -441,6 +447,16 @@ nsAttrValue::ToString(nsAString& aResult) const
|
|||
aResult = str;
|
||||
break;
|
||||
}
|
||||
// No need to do for eLazyURIValue, since that always stores the
|
||||
// original string.
|
||||
#ifdef DEBUG
|
||||
case eLazyURIValue:
|
||||
{
|
||||
NS_NOTREACHED("Shouldn't get here");
|
||||
aResult.Truncate();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
aResult.Truncate();
|
||||
|
@ -576,6 +592,17 @@ nsAttrValue::HashValue() const
|
|||
// XXX this is crappy, but oh well
|
||||
return cont->mFloatValue;
|
||||
}
|
||||
case eLazyURIValue:
|
||||
{
|
||||
NS_ASSERTION(static_cast<ValueBaseType>(cont->mStringBits &
|
||||
NS_ATTRVALUE_BASETYPE_MASK) ==
|
||||
eStringBase,
|
||||
"Unexpected type");
|
||||
nsStringBuffer* str = static_cast<nsStringBuffer*>(MISC_STR_PTR(cont));
|
||||
NS_ASSERTION(str, "How did that happen?");
|
||||
PRUint32 len = str->StorageSize()/sizeof(PRUnichar) - 1;
|
||||
return nsCRT::BufferHashCode(static_cast<PRUnichar*>(str->Data()), len);
|
||||
}
|
||||
default:
|
||||
{
|
||||
NS_NOTREACHED("unknown type stored in MiscContainer");
|
||||
|
@ -678,6 +705,11 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const
|
|||
{
|
||||
return thisCont->mFloatValue == otherCont->mFloatValue;
|
||||
}
|
||||
case eLazyURIValue:
|
||||
{
|
||||
needsStringComparison = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
NS_NOTREACHED("unknown type stored in MiscContainer");
|
||||
|
@ -1139,6 +1171,58 @@ PRBool nsAttrValue::ParseFloatValue(const nsAString& aString)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool nsAttrValue::ParseLazyURIValue(const nsAString& aString)
|
||||
{
|
||||
ResetIfSet();
|
||||
|
||||
if (EnsureEmptyMiscContainer()) {
|
||||
MiscContainer* cont = GetMiscContainer();
|
||||
cont->mURI = nsnull;
|
||||
cont->mType = eLazyURIValue;
|
||||
|
||||
// Don't use SetMiscAtomOrString because atomizing URIs is not
|
||||
// likely to do us much good.
|
||||
nsStringBuffer* buf = GetStringBuffer(aString);
|
||||
if (!buf) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
cont->mStringBits = reinterpret_cast<PtrBits>(buf) | eStringBase;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsAttrValue::CacheURIValue(nsIURI* aURI)
|
||||
{
|
||||
NS_PRECONDITION(Type() == eLazyURIValue, "wrong type");
|
||||
NS_PRECONDITION(!GetMiscContainer()->mURI, "Why are we being called?");
|
||||
NS_IF_ADDREF(GetMiscContainer()->mURI = aURI);
|
||||
}
|
||||
|
||||
void
|
||||
nsAttrValue::DropCachedURI()
|
||||
{
|
||||
NS_PRECONDITION(Type() == eLazyURIValue, "wrong type");
|
||||
NS_IF_RELEASE(GetMiscContainer()->mURI);
|
||||
}
|
||||
|
||||
const nsCheapString
|
||||
nsAttrValue::GetURIStringValue() const
|
||||
{
|
||||
NS_PRECONDITION(Type() == eLazyURIValue, "wrong type");
|
||||
NS_PRECONDITION(static_cast<ValueBaseType>(GetMiscContainer()->mStringBits &
|
||||
NS_ATTRVALUE_BASETYPE_MASK) ==
|
||||
eStringBase,
|
||||
"Unexpected type");
|
||||
NS_PRECONDITION(MISC_STR_PTR(GetMiscContainer()),
|
||||
"Should have a string buffer here!");
|
||||
return nsCheapString(static_cast<nsStringBuffer*>
|
||||
(MISC_STR_PTR(GetMiscContainer())));
|
||||
}
|
||||
|
||||
void
|
||||
nsAttrValue::SetMiscAtomOrString(const nsAString* aValue)
|
||||
{
|
||||
|
@ -1204,6 +1288,11 @@ nsAttrValue::EnsureEmptyMiscContainer()
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
case eLazyURIValue:
|
||||
{
|
||||
NS_IF_RELEASE(cont->mURI);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
|
|
|
@ -54,6 +54,7 @@ typedef PRUptrdiff PtrBits;
|
|||
class nsAString;
|
||||
class nsIAtom;
|
||||
class nsICSSStyleRule;
|
||||
class nsIURI;
|
||||
class nsISVGValue;
|
||||
class nsIDocument;
|
||||
template<class E> class nsCOMArray;
|
||||
|
@ -120,6 +121,7 @@ public:
|
|||
,eSVGValue = 0x12
|
||||
#endif
|
||||
,eFloatValue = 0x13
|
||||
,eLazyURIValue = 0x14
|
||||
};
|
||||
|
||||
ValueType Type() const;
|
||||
|
@ -153,6 +155,10 @@ public:
|
|||
inline nsISVGValue* GetSVGValue() const;
|
||||
#endif
|
||||
inline float GetFloatValue() const;
|
||||
inline nsIURI* GetURIValue() const;
|
||||
const nsCheapString GetURIStringValue() const;
|
||||
void CacheURIValue(nsIURI* aURI);
|
||||
void DropCachedURI();
|
||||
|
||||
// Methods to get access to atoms we may have
|
||||
// Returns the number of atoms we have; 0 if we have none. It's OK
|
||||
|
@ -291,6 +297,7 @@ private:
|
|||
nsISVGValue* mSVGValue;
|
||||
#endif
|
||||
float mFloatValue;
|
||||
nsIURI* mURI;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -397,6 +404,13 @@ nsAttrValue::GetFloatValue() const
|
|||
return GetMiscContainer()->mFloatValue;
|
||||
}
|
||||
|
||||
inline nsIURI*
|
||||
nsAttrValue::GetURIValue() const
|
||||
{
|
||||
NS_PRECONDITION(Type() == eLazyURIValue, "wrong type");
|
||||
return GetMiscContainer()->mURI;
|
||||
}
|
||||
|
||||
inline nsAttrValue::ValueBaseType
|
||||
nsAttrValue::BaseType() const
|
||||
{
|
||||
|
|
|
@ -2108,6 +2108,19 @@ nsGenericHTMLElement::GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr,
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool isURIAttr = (attr->Type() == nsAttrValue::eLazyURIValue);
|
||||
|
||||
if (isURIAttr && (*aURI = attr->GetURIValue())) {
|
||||
if (aCloneIfCached) {
|
||||
nsIURI* clone = nsnull;
|
||||
(*aURI)->Clone(&clone);
|
||||
*aURI = clone;
|
||||
} else {
|
||||
NS_ADDREF(*aURI);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
|
||||
|
||||
if (aBaseAttr) {
|
||||
|
@ -2128,8 +2141,18 @@ nsGenericHTMLElement::GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr,
|
|||
// Don't care about return value. If it fails, we still want to
|
||||
// return PR_TRUE, and *aURI will be null.
|
||||
nsContentUtils::NewURIWithDocumentCharset(aURI,
|
||||
isURIAttr ?
|
||||
attr->GetURIStringValue() :
|
||||
attr->GetStringValue(),
|
||||
GetOwnerDoc(), baseURI);
|
||||
|
||||
// We may have to re-resolve all our cached hrefs when the document's base
|
||||
// URI changes. The base URI depends on the owner document, but it's the
|
||||
// current document that keeps track of links. If the two documents don't
|
||||
// match, we shouldn't cache.
|
||||
if (isURIAttr && GetOwnerDoc() == GetCurrentDoc()) {
|
||||
const_cast<nsAttrValue*>(attr)->CacheURIValue(*aURI);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -2997,6 +3020,13 @@ nsGenericHTMLElement::SetHrefToURI(nsIURI* aURI)
|
|||
nsCAutoString newHref;
|
||||
aURI->GetSpec(newHref);
|
||||
SetAttrHelper(nsGkAtoms::href, NS_ConvertUTF8toUTF16(newHref));
|
||||
const nsAttrValue* attr = mAttrsAndChildren.GetAttr(nsGkAtoms::href);
|
||||
// Might already have a URI value, if we didn't actually change the
|
||||
// string value of our attribute.
|
||||
if (attr && attr->Type() == nsAttrValue::eLazyURIValue &&
|
||||
!attr->GetURIValue()) {
|
||||
const_cast<nsAttrValue*>(attr)->CacheURIValue(aURI);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -132,6 +132,9 @@ public:
|
|||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
|
||||
virtual void DropCachedHref();
|
||||
|
||||
protected:
|
||||
void ResetLinkCacheState();
|
||||
};
|
||||
|
||||
|
||||
|
@ -219,7 +222,7 @@ nsHTMLAnchorElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
|||
{
|
||||
if (IsInDoc()) {
|
||||
RegUnRegAccessKey(PR_FALSE);
|
||||
Link::ResetLinkState();
|
||||
ResetLinkCacheState();
|
||||
}
|
||||
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
|
@ -436,7 +439,7 @@ nsHTMLAnchorElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
nsAutoString val;
|
||||
GetHref(val);
|
||||
if (!val.Equals(aValue)) {
|
||||
Link::ResetLinkState();
|
||||
ResetLinkCacheState();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,7 +463,7 @@ nsHTMLAnchorElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
|||
PRBool aNotify)
|
||||
{
|
||||
if (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
|
||||
Link::ResetLinkState();
|
||||
ResetLinkCacheState();
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::accesskey &&
|
||||
|
@ -477,6 +480,10 @@ nsHTMLAnchorElement::ParseAttribute(PRInt32 aNamespaceID,
|
|||
const nsAString& aValue,
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
if (aNamespaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::href) {
|
||||
return aResult.ParseLazyURIValue(aValue);
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
|
||||
aResult);
|
||||
}
|
||||
|
@ -484,5 +491,24 @@ nsHTMLAnchorElement::ParseAttribute(PRInt32 aNamespaceID,
|
|||
void
|
||||
nsHTMLAnchorElement::DropCachedHref()
|
||||
{
|
||||
Link::ResetLinkState();
|
||||
nsAttrValue* attr =
|
||||
const_cast<nsAttrValue*>(mAttrsAndChildren.GetAttr(nsGkAtoms::href));
|
||||
|
||||
if (!attr || attr->Type() != nsAttrValue::eLazyURIValue)
|
||||
return;
|
||||
|
||||
attr->DropCachedURI();
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLAnchorElement::ResetLinkCacheState()
|
||||
{
|
||||
Link::ResetLinkState();
|
||||
|
||||
// Clear our cached URI _after_ we ForgetLink(), since ForgetLink()
|
||||
// wants that URI.
|
||||
const nsAttrValue* attr = mAttrsAndChildren.GetAttr(nsGkAtoms::href);
|
||||
if (attr && attr->Type() == nsAttrValue::eLazyURIValue) {
|
||||
const_cast<nsAttrValue*>(attr)->DropCachedURI();
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче