Backed out changeset 06b691e8cbcd

This commit is contained in:
Shawn Wilsher 2010-02-18 10:08:54 -08:00
Родитель a37874c892
Коммит 291a108475
4 изменённых файлов: 168 добавлений и 9 удалений

Просмотреть файл

@ -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();
}
}