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:
jst%netscape.com 2001-10-24 07:15:06 +00:00
Родитель 28becb73f9
Коммит a9979d7127
9 изменённых файлов: 111 добавлений и 35 удалений

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

@ -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;