From bb5db125e3cca2988a94f84faaafa70618da88a4 Mon Sep 17 00:00:00 2001 From: "jband%netscape.com" Date: Fri, 2 Feb 2001 08:48:28 +0000 Subject: [PATCH] part of the fix for bug 67258 to avoid empry Components.results. r=dmose sr=brendan xpccomponents.cpp --- js/src/xpconnect/src/xpccomponents.cpp | 31 +++++++++--- js/src/xpconnect/src/xpcconvert.cpp | 70 ++++++++++++++++++++++++-- js/src/xpconnect/src/xpcjsid.cpp | 11 ++-- 3 files changed, 97 insertions(+), 15 deletions(-) diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp index 778e680c949..f1ac7cf0db0 100644 --- a/js/src/xpconnect/src/xpccomponents.cpp +++ b/js/src/xpconnect/src/xpccomponents.cpp @@ -908,12 +908,30 @@ private: nsIXPConnectWrappedNative *wrapper, nsIXPCScriptable *arbitrary); + JSBool NeedToFillCache(JSObject* obj) const {return obj != mObj;} + private: - JSBool mCacheFilled; + // + // This code used to just use a JSBool to track whether or not we had + // already added the properties to the JSObject. The problem with that + // scheme is that we are storing the flag here in this C++ object, but the + // properties get added to the JSObject of the wrapper around this object. + // Usually this worked fine. But in the cases where the wrapper was + // garbage collected and a new wrapper created in its place our flag would + // indicate that we'd added the properties, but those properties had been + // added to the JSObject of the *old* wrapper but the new wrapper's JSObject + // would not have the properties at all. + // + // So instead, we flag the addition of the properties by storing the + // JSObject* on which we added the properties. If mObj equals the + // current object then we know we've added the properties. Otherwise we + // know we still need to add them. + // + JSObject* mObj; }; nsXPCComponents_Results::nsXPCComponents_Results() - : mCacheFilled(JS_FALSE) + : mObj(nsnull) { NS_INIT_ISUPPORTS(); } @@ -950,7 +968,8 @@ nsXPCComponents_Results::FillCache(JSContext *cx, JSObject *obj, } } - mCacheFilled = JS_TRUE; + // Indicate that we've added the properties to the current object. + mObj = obj; return; } @@ -992,7 +1011,7 @@ nsXPCComponents_Results::LookupProperty(JSContext *cx, JSObject *obj, nsIXPCScriptable* arbitrary, JSBool* retval) { - if(!mCacheFilled) + if(NeedToFillCache(obj)) FillCache(cx, obj, wrapper, arbitrary); return arbitrary->LookupProperty(cx, obj, id, objp, propp, wrapper, nsnull, retval); @@ -1005,7 +1024,7 @@ nsXPCComponents_Results::GetProperty(JSContext *cx, JSObject *obj, nsIXPCScriptable* arbitrary, JSBool* retval) { - if(!mCacheFilled) + if(NeedToFillCache(obj)) FillCache(cx, obj, wrapper, arbitrary); return arbitrary->GetProperty(cx, obj, id, vp, wrapper, nsnull, retval); } @@ -1019,7 +1038,7 @@ nsXPCComponents_Results::Enumerate(JSContext *cx, JSObject *obj, nsIXPCScriptable *arbitrary, JSBool *retval) { - if(enum_op == JSENUMERATE_INIT && !mCacheFilled) + if(enum_op == JSENUMERATE_INIT && NeedToFillCache(obj)) FillCache(cx, obj, wrapper, arbitrary); return arbitrary->Enumerate(cx, obj, enum_op, statep, idp, wrapper, diff --git a/js/src/xpconnect/src/xpcconvert.cpp b/js/src/xpconnect/src/xpcconvert.cpp index 5b2b66ffd1b..4f6dc42b3d0 100644 --- a/js/src/xpconnect/src/xpcconvert.cpp +++ b/js/src/xpconnect/src/xpcconvert.cpp @@ -90,7 +90,7 @@ static uint8 xpc_reflectable_flags[XPC_FLAG_COUNT] = { XPC_MK_FLAG( 1 , 1 , 1 , 0 ), /* T_WCHAR */ XPC_MK_FLAG( 0 , 0 , 0 , 0 ), /* T_VOID */ XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_IID */ - XPC_MK_FLAG( 0 , 0 , 0 , 0 ), /* T_DOMSTRING */ + XPC_MK_FLAG( 0 , 1 , 0 , 0 ), /* T_DOMSTRING */ XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_CHAR_STR */ XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_WCHAR_STR */ XPC_MK_FLAG( 0 , 1 , 0 , 1 ), /* T_INTERFACE */ @@ -347,9 +347,35 @@ XPCConvert::NativeData2JS(JSContext* cx, jsval* d, const void* s, } case nsXPTType::T_DOMSTRING: - // XXX implement DOMSTRING - XPC_LOG_ERROR(("XPCConvert::NativeData2JS : DOMSTRING params not supported")); - return JS_FALSE; + { + const nsAReadableString* p = *((const nsAReadableString**)s); + if(!p) + break; + + PRUint32 length = p->Length(); + + jschar* chars = (jschar *) + JS_malloc(cx, (length + 1) * sizeof(jschar)); + if(!chars) + return JS_FALSE; + + if(length && !CopyUnicodeTo(*p, 0, (PRUnichar*)chars, length)) + { + JS_free(cx, chars); + return JS_FALSE; + } + + chars[length] = 0; + + JSString* str; + if(!(str = JS_NewUCString(cx, chars, length))) + { + JS_free(cx, chars); + return JS_FALSE; + } + *d = STRING_TO_JSVAL(str); + break; + } case nsXPTType::T_CHAR_STR: { @@ -586,6 +612,42 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s, } case nsXPTType::T_DOMSTRING: + { + const PRUnichar* chars = nsnull; + PRUint32 length; + JSString* str; + + if(!JSVAL_IS_VOID(s) && !JSVAL_IS_NULL(s) && + nsnull != (str = JS_ValueToString(cx, s))) + { + chars = (const PRUnichar*) JS_GetStringChars(str); + length = (PRUint32) JS_GetStringLength(str); + } + + // XXX We don't yet have a way to represent a null nsAXXXString + // (as opposed to one containing an empty string). This comes later. + + const static PRUnichar* emptyString = NS_LITERAL_STRING(""); + if(!chars) + { + chars = emptyString; + length = 0; + } + + if(useAllocator) + { + nsAReadableString* rs = new nsLiteralString(chars, length); + if(!rs) + return JS_FALSE; + *((nsAReadableString**)d) = rs; + } + else + { + nsAWritableString* ws = *((nsAWritableString**)d); + ws->Assign(chars); + } + return JS_TRUE; + } // XXX implement DOMSTRING XPC_LOG_ERROR(("XPCConvert::JSData2Native : DOMSTRING params not supported")); return JS_FALSE; diff --git a/js/src/xpconnect/src/xpcjsid.cpp b/js/src/xpconnect/src/xpcjsid.cpp index 27102cdd8bb..35fea24265b 100644 --- a/js/src/xpconnect/src/xpcjsid.cpp +++ b/js/src/xpconnect/src/xpcjsid.cpp @@ -274,7 +274,7 @@ XPC_IMPLEMENT_IGNORE_CONSTRUCT(nsJSIID) XPC_IMPLEMENT_FORWARD_FINALIZE(nsJSIID) nsJSIID::nsJSIID() - : mCacheFilled(JS_FALSE) + : mObj(nsnull) { NS_INIT_ISUPPORTS(); } @@ -479,7 +479,8 @@ nsJSIID::FillCache(JSContext *cx, JSObject *obj, } } - mCacheFilled = JS_TRUE; + // Indicate that we've added the properties to the current object. + mObj = obj; return; } @@ -502,7 +503,7 @@ nsJSIID::LookupProperty(JSContext *cx, JSObject *obj, nsIXPCScriptable* arbitrary, JSBool* retval) { - if(!mCacheFilled) + if(NeedToFillCache(obj)) FillCache(cx, obj, wrapper, arbitrary); return arbitrary->LookupProperty(cx, obj, id, objp, propp, wrapper, nsnull, retval); @@ -515,7 +516,7 @@ nsJSIID::GetProperty(JSContext *cx, JSObject *obj, nsIXPCScriptable* arbitrary, JSBool* retval) { - if(!mCacheFilled) + if(NeedToFillCache(obj)) FillCache(cx, obj, wrapper, arbitrary); return arbitrary->GetProperty(cx, obj, id, vp, wrapper, nsnull, retval); } @@ -529,7 +530,7 @@ nsJSIID::Enumerate(JSContext *cx, JSObject *obj, nsIXPCScriptable *arbitrary, JSBool *retval) { - if(enum_op == JSENUMERATE_INIT && !mCacheFilled) + if(enum_op == JSENUMERATE_INIT && NeedToFillCache(obj)) FillCache(cx, obj, wrapper, arbitrary); return arbitrary->Enumerate(cx, obj, enum_op, statep, idp, wrapper,