зеркало из https://github.com/mozilla/pjs.git
Fixing bug 69468. Finally adding support for string nullness to XPConnect. r=jaggernaut@netscape.com, shaver@mozilla.org, sr=jband@netscape.com
This commit is contained in:
Родитель
28becb73f9
Коммит
a9979d7127
|
@ -80,7 +80,8 @@ nsresult nsXULAttributeValue::GetValue( nsAWritableString& aResult )
|
|||
}
|
||||
|
||||
|
||||
nsresult nsXULAttributeValue::SetValue(const nsAReadableString& aValue, PRBool forceAtom)
|
||||
nsresult nsXULAttributeValue::SetValue(const nsAReadableString& aValue,
|
||||
PRBool forceAtom)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> newAtom;
|
||||
|
||||
|
@ -89,7 +90,10 @@ nsresult nsXULAttributeValue::SetValue(const nsAReadableString& aValue, PRBool f
|
|||
// atom table: the style system frequently asks for it, and if the
|
||||
// table is "unprimed" we see quite a bit of thrashing as the 'id'
|
||||
// value is repeatedly added and then removed from the atom table.
|
||||
if ((aValue.Length() <= kMaxAtomValueLength) || forceAtom)
|
||||
|
||||
PRUint32 len = aValue.Length();
|
||||
|
||||
if (len && ((len <= kMaxAtomValueLength) || forceAtom))
|
||||
{
|
||||
newAtom = getter_AddRefs( NS_NewAtom(aValue) );
|
||||
}
|
||||
|
@ -104,10 +108,14 @@ nsresult nsXULAttributeValue::SetValue(const nsAReadableString& aValue, PRBool f
|
|||
mValue = (void*)(PRWord(newAtom.get()) | kAtomType);
|
||||
}
|
||||
else {
|
||||
PRUnichar* str = ToNewUnicode(aValue);
|
||||
if (! str)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PRUnichar* str = nsnull;
|
||||
|
||||
if (len) {
|
||||
str = ToNewUnicode(aValue);
|
||||
if (! str)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mValue = str;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,15 +45,13 @@
|
|||
|
||||
inline PRBool DOMStringIsNull(const nsAReadableString& aString)
|
||||
{
|
||||
// Null string code goes here.
|
||||
|
||||
return PR_FALSE;
|
||||
return aString.IsVoid();
|
||||
}
|
||||
|
||||
inline void SetDOMStringToNull(nsAWritableString& aString)
|
||||
{
|
||||
aString.Truncate();
|
||||
// Set aString to null here.
|
||||
aString.SetIsVoid(PR_TRUE);
|
||||
}
|
||||
|
||||
%}
|
||||
|
|
|
@ -290,11 +290,18 @@ XPCConvert::NativeData2JS(XPCCallContext& ccx, jsval* d, const void* s,
|
|||
if(!p)
|
||||
break;
|
||||
|
||||
JSString *str = XPCStringConvert::ReadableToJSString(cx, *p);
|
||||
if(!str)
|
||||
return JS_FALSE;
|
||||
if(!p->IsVoid()) {
|
||||
JSString *str =
|
||||
XPCStringConvert::ReadableToJSString(cx, *p);
|
||||
if(!str)
|
||||
return JS_FALSE;
|
||||
|
||||
*d = STRING_TO_JSVAL(str);
|
||||
}
|
||||
|
||||
// *d is defaulted to JSVAL_NULL so no need to set it
|
||||
// again if p is a "void" string
|
||||
|
||||
*d = STRING_TO_JSVAL(str);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -535,7 +542,6 @@ XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s,
|
|||
case nsXPTType::T_DOMSTRING:
|
||||
{
|
||||
static const NS_NAMED_LITERAL_STRING(sEmptyString, "");
|
||||
static const NS_NAMED_LITERAL_STRING(sNullString, "null");
|
||||
static const NS_NAMED_LITERAL_STRING(sVoidString, "undefined");
|
||||
|
||||
const PRUnichar* chars;
|
||||
|
@ -548,14 +554,7 @@ XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s,
|
|||
chars = sVoidString.get();
|
||||
length = sVoidString.Length();
|
||||
}
|
||||
else if(JSVAL_IS_NULL(s))
|
||||
{
|
||||
// XXX We don't yet have a way to represent a null nsAXXXString
|
||||
// XXX Do we *want* to use "null"?
|
||||
chars = sNullString.get();
|
||||
length = sNullString.Length();
|
||||
}
|
||||
else
|
||||
else if(!JSVAL_IS_NULL(s))
|
||||
{
|
||||
str = JS_ValueToString(cx, s);
|
||||
if(!str)
|
||||
|
@ -577,8 +576,6 @@ XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s,
|
|||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(chars, "I must be really confused");
|
||||
|
||||
if(useAllocator)
|
||||
{
|
||||
if(str)
|
||||
|
@ -591,13 +588,22 @@ XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s,
|
|||
// Ask for the shared buffer handle, which will root the
|
||||
// string.
|
||||
if(isNewString && ! wrapper->GetSharedBufferHandle())
|
||||
return JS_FALSE;
|
||||
return JS_FALSE;
|
||||
|
||||
*((nsAReadableString**)d) = wrapper;
|
||||
}
|
||||
else if(JSVAL_IS_NULL(s))
|
||||
{
|
||||
XPCReadableJSStringWrapper *wrapper =
|
||||
new XPCReadableJSStringWrapper();
|
||||
if(!wrapper)
|
||||
return JS_FALSE;
|
||||
|
||||
*((nsAReadableString**)d) = wrapper;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsAReadableString *rs = new nsString(chars, length);
|
||||
nsAReadableString *rs = new nsAutoString(chars, length);
|
||||
if(!rs)
|
||||
return JS_FALSE;
|
||||
*((nsAReadableString**)d) = rs;
|
||||
|
@ -606,7 +612,11 @@ XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s,
|
|||
else
|
||||
{
|
||||
nsAWritableString* ws = *((nsAWritableString**)d);
|
||||
ws->Assign(chars);
|
||||
|
||||
if(JSVAL_IS_NULL(s))
|
||||
ws->SetIsVoid(PR_TRUE);
|
||||
else
|
||||
ws->Assign(chars);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
|
|
@ -2212,11 +2212,16 @@ class XPCReadableJSStringWrapper : public nsDependentString
|
|||
public:
|
||||
XPCReadableJSStringWrapper(JSString *str) :
|
||||
nsDependentString(NS_REINTERPRET_CAST(PRUnichar *,
|
||||
JS_GetStringChars(str)),
|
||||
JS_GetStringChars(str)),
|
||||
JS_GetStringLength(str)),
|
||||
mStr(str), mBufferHandle(0), mHandleIsShared(JS_FALSE)
|
||||
{ }
|
||||
|
||||
XPCReadableJSStringWrapper() :
|
||||
nsDependentString(nsnull, (PRUint32)0), mStr(nsnull),
|
||||
mBufferHandle(nsnull), mHandleIsShared(JS_FALSE)
|
||||
{ }
|
||||
|
||||
~XPCReadableJSStringWrapper();
|
||||
|
||||
// buffer-handle accessors
|
||||
|
@ -2230,6 +2235,11 @@ public:
|
|||
return BufferHandle(JS_TRUE);
|
||||
}
|
||||
|
||||
PRBool IsVoid() const
|
||||
{
|
||||
return mStr == nsnull;
|
||||
}
|
||||
|
||||
protected:
|
||||
struct WrapperBufferHandle :
|
||||
public nsSharedBufferHandleWithAllocator<PRUnichar>
|
||||
|
@ -2267,6 +2277,41 @@ protected:
|
|||
JSBool mHandleIsShared;
|
||||
};
|
||||
|
||||
// "voidable" nsAString implementation
|
||||
class XPCVoidableString : public nsAutoString
|
||||
{
|
||||
public:
|
||||
XPCVoidableString() :
|
||||
nsAutoString(), mIsVoid(PR_FALSE)
|
||||
{ }
|
||||
|
||||
char_type* GetWritableFragment(nsWritableFragment<char_type>& aFragment,
|
||||
nsFragmentRequest aRequest,
|
||||
PRUint32 aOffset)
|
||||
{
|
||||
mIsVoid = PR_FALSE;
|
||||
|
||||
return nsAutoString::GetWritableFragment(aFragment, aRequest, aOffset);
|
||||
}
|
||||
|
||||
PRBool IsVoid() const
|
||||
{
|
||||
return mIsVoid;
|
||||
}
|
||||
|
||||
void SetIsVoid(PRBool aVoid)
|
||||
{
|
||||
if(aVoid && !mIsVoid) {
|
||||
Truncate();
|
||||
}
|
||||
|
||||
mIsVoid = aVoid;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRBool mIsVoid;
|
||||
};
|
||||
|
||||
// readable string conversions, static methods only
|
||||
class XPCStringConvert
|
||||
{
|
||||
|
|
|
@ -77,6 +77,11 @@ XPCReadableJSStringWrapper::~XPCReadableJSStringWrapper()
|
|||
const nsSharedBufferHandle<PRUnichar>*
|
||||
XPCReadableJSStringWrapper::BufferHandle(JSBool shared) const
|
||||
{
|
||||
if (!mStr) {
|
||||
// This is a "void" string, no buffer handle available
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
XPCReadableJSStringWrapper * mutable_this =
|
||||
NS_CONST_CAST(XPCReadableJSStringWrapper *, this);
|
||||
|
||||
|
|
|
@ -1750,7 +1750,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
|
|||
// Is an 'out' DOMString. Make a new nsAWritableString
|
||||
// now and then continue in order to skip the call to
|
||||
// JSData2Native
|
||||
if(!(dp->val.p = new nsString()))
|
||||
if(!(dp->val.p = new XPCVoidableString()))
|
||||
{
|
||||
JS_ReportOutOfMemory(ccx);
|
||||
goto done;
|
||||
|
|
|
@ -172,8 +172,10 @@ nsOutlinerColumn::nsOutlinerColumn(nsIContent* aColElement, nsIFrame* aFrame)
|
|||
// Fetch the ID.
|
||||
mColElement->GetAttr(kNameSpaceID_None, nsHTMLAtoms::id, mID);
|
||||
|
||||
// Cache the ID as an atom.
|
||||
mIDAtom = getter_AddRefs(NS_NewAtom(mID));
|
||||
// If we have an ID, cache the ID as an atom.
|
||||
if (!mID.IsEmpty()) {
|
||||
mIDAtom = getter_AddRefs(NS_NewAtom(mID));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStyleContext> styleContext;
|
||||
aFrame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
|
|
|
@ -172,8 +172,10 @@ nsOutlinerColumn::nsOutlinerColumn(nsIContent* aColElement, nsIFrame* aFrame)
|
|||
// Fetch the ID.
|
||||
mColElement->GetAttr(kNameSpaceID_None, nsHTMLAtoms::id, mID);
|
||||
|
||||
// Cache the ID as an atom.
|
||||
mIDAtom = getter_AddRefs(NS_NewAtom(mID));
|
||||
// If we have an ID, cache the ID as an atom.
|
||||
if (!mID.IsEmpty()) {
|
||||
mIDAtom = getter_AddRefs(NS_NewAtom(mID));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStyleContext> styleContext;
|
||||
aFrame->GetStyleContext(getter_AddRefs(styleContext));
|
||||
|
|
|
@ -68,7 +68,7 @@ AtomTableGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
|
|||
PR_STATIC_CALLBACK(PLDHashNumber)
|
||||
AtomTableHashKey(PLDHashTable *table, const void *key)
|
||||
{
|
||||
return nsCRT::HashCode(NS_STATIC_CAST(const PRUnichar*,key));
|
||||
return nsCRT::HashCode(NS_STATIC_CAST(const PRUnichar*, key));
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
|
@ -273,6 +273,12 @@ static AtomTableEntry* GetAtomHashEntry(const nsAString& aString)
|
|||
|
||||
NS_COM nsIAtom* NS_NewAtom( const nsAString& aString )
|
||||
{
|
||||
if (aString.IsEmpty()) {
|
||||
NS_ERROR("Atom requested for empty string!");
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
AtomTableEntry *he = GetAtomHashEntry(aString);
|
||||
AtomImpl* atom = he->mAtom;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче