Bug 205768 - Enumeration of wrapped IDispatch objects is broken. r=adamlock, sr=alecf.

git-svn-id: svn://10.0.0.236/trunk@143329 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dbradley%netscape.com 2003-06-05 11:57:03 +00:00
parent bd9829ca93
commit 8ae82d7e06
4 changed files with 325 additions and 140 deletions

View File

@ -1137,30 +1137,6 @@ public:
*/
static JSBool Initialize(JSContext * aJSContext,
JSObject* aGlobalJSObj);
/**
* This is the define property for the IDispatch system. It called from
* the XPConnect's DefineProperty
* @param ccx an XPConnect call context
* @param obj the JS object receiving the property
* @param idval ID of the property to add
* @param wrapperToReflectInterfaceNames the wrapper
* @param propFlags JS property flags
* @param resolved a pointer to a JSBool, set to true if properly resolved
*/
static JSBool DefineProperty(XPCCallContext & ccx,
JSObject *obj, jsval idval,
XPCWrappedNative* wrapperToReflectInterfaceNames,
uintN propFlags, JSBool* resolved);
/**
* IDispatch system's enumeration function. This is called
* from XPC_WN_Shared_Enumerate
* @param ccx a XPConnect call context
* @param obj pointer to the JSObject
* @param wrapper pointer to the wrapper
* @return true if the enumeration was successful
*/
static JSBool Enumerate(XPCCallContext& ccx, JSObject* obj,
XPCWrappedNative * wrapper);
/**
* This is the delegated QI called from the wrapped JS class
* DelegatedQueryInterface

View File

@ -38,6 +38,328 @@
#include "xpcprivate.h"
#include "nsCRT.h"
class XPCIDispatchScriptableHelper : public nsIXPCScriptable
{
public:
/**
* Returns a single instance of XPCIDispatchScriptableHelper
* @return the lone instance
*/
static XPCIDispatchScriptableHelper* GetSingleton();
/**
* Releases our hold on the instance
*/
static void FreeSingleton();
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCSCRIPTABLE
private:
/**
* Only our methods create and destroy instances
*/
XPCIDispatchScriptableHelper();
virtual ~XPCIDispatchScriptableHelper();
static XPCIDispatchScriptableHelper* sInstance;
};
XPCIDispatchScriptableHelper* XPCIDispatchScriptableHelper::sInstance = nsnull;
NS_IMPL_ISUPPORTS1(XPCIDispatchScriptableHelper, nsIXPCScriptable)
XPCIDispatchScriptableHelper * XPCIDispatchScriptableHelper::GetSingleton()
{
if (!sInstance)
{
sInstance = new XPCIDispatchScriptableHelper;
NS_IF_ADDREF(sInstance);
}
NS_IF_ADDREF(sInstance);
return sInstance;
}
void XPCIDispatchScriptableHelper::FreeSingleton()
{
NS_IF_RELEASE(sInstance);
}
XPCIDispatchScriptableHelper::XPCIDispatchScriptableHelper()
{
/* member initializers and constructor code */
}
XPCIDispatchScriptableHelper::~XPCIDispatchScriptableHelper()
{
/* destructor code */
}
/* readonly attribute string className; */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::GetClassName(char * *aClassName)
{
static const char className[] = "IDispatch";
if(!aClassName)
return NS_ERROR_NULL_POINTER;
*aClassName = (char*) nsMemory::Clone(className, sizeof(className));
return NS_OK;
}
/* readonly attribute PRUint32 scriptableFlags; */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::GetScriptableFlags(PRUint32 *aScriptableFlags)
{
*aScriptableFlags = DONT_SHARE_PROTOTYPE | DONT_ENUM_QUERY_INTERFACE |
WANT_ENUMERATE | WANT_NEWRESOLVE |
ALLOW_PROP_MODS_DURING_RESOLVE |
DONT_ASK_INSTANCE_FOR_SCRIPTABLE;
return NS_OK;
}
/* void preCreate (in nsISupports nativeObj, in JSContextPtr cx, in JSObjectPtr globalObj, out JSObjectPtr parentObj); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::PreCreate(nsISupports *nativeObj, JSContext * cx,
JSObject * globalObj,
JSObject * *parentObj)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void create (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::Create(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void postCreate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::PostCreate(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRBool addProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::AddProperty(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
jsval id, jsval * vp, PRBool *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRBool delProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::DelProperty(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
jsval id, jsval * vp, PRBool *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRBool getProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::GetProperty(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
jsval id, jsval * vp, PRBool *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRBool setProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::SetProperty(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
jsval id, jsval * vp, PRBool *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRBool enumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::Enumerate(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
PRBool *retval)
{
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCNativeInterface* iface = XPCNativeInterface::GetNewOrUsed(
ccx,&NSID_IDISPATCH);
if(!iface)
return JS_FALSE;
XPCWrappedNativeTearOff* tearoff = ccx.GetWrapper()->FindTearOff(ccx, iface);
if(!tearoff)
return JS_FALSE;
XPCDispInterface* pInfo = tearoff->GetIDispatchInfo();
PRUint32 members = pInfo->GetMemberCount();
// Iterate over the members and force the properties to be resolved
for(PRUint32 index = 0; index < members; ++index)
{
const XPCDispInterface::Member & member = pInfo->GetMember(index);
jsval name = member.GetName();
if(!xpc_ForcePropertyResolve(ccx, obj, name))
return JS_FALSE;
}
*retval = PR_TRUE;
return NS_OK;
}
/* PRBool newEnumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 enum_op, in JSValPtr statep, out JSID idp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
PRUint32 enum_op, jsval * statep,
jsid *idp, PRBool *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::NewResolve(nsIXPConnectWrappedNative *wrappedNative,
JSContext * cx, JSObject * obj,
jsval idval, PRUint32 flags,
JSObject * *objp, PRBool *retval)
{
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative * wrapper = ccx.GetWrapper();
*retval = PR_FALSE;
// Check to see if there's an IDispatch tearoff
if(!JSVAL_IS_STRING(idval))
return NS_OK;
// Look up the native interface for IDispatch and then find a tearoff
XPCNativeInterface* iface = XPCNativeInterface::GetNewOrUsed(ccx,
"IDispatch");
if(iface == nsnull)
return NS_OK;
XPCWrappedNativeTearOff* to = wrapper->FindTearOff(ccx, iface, JS_TRUE);
if(to == nsnull)
return NS_OK;
// get the JS Object for the tea
JSObject* jso = to->GetJSObject();
if(jso == nsnull)
return NS_OK;
// Look up the member in the interface
const XPCDispInterface::Member * member = to->GetIDispatchInfo()->FindMember(idval);
if(!member)
{
// IDispatch is case insensitive, so if we don't find a case sensitive
// match, we'll try a more expensive case-insensisitive search
// TODO: We need to create cleaner solution that doesn't create
// multiple properties of different case on the JS Object
member = to->GetIDispatchInfo()->FindMemberCI(ccx, idval);
if(!member)
return NS_OK;
}
// Get the function object
jsval funval;
if(!member->GetValue(ccx, iface, &funval))
return NS_OK;
// Protect the jsval
AUTO_MARK_JSVAL(ccx, funval);
// clone a function we can use for this object
JSObject* funobj = JS_CloneFunctionObject(ccx, JSVAL_TO_OBJECT(funval), obj);
if(!funobj)
return NS_OK;
jsid id;
flags |= JSPROP_ENUMERATE;
// If this is a function or a parameterized property
if(member->IsFunction() || member->IsParameterizedProperty())
{
// define the function on the object
AutoResolveName arn(ccx, idval);
*objp = obj;
*retval = JS_ValueToId(ccx, idval, &id) &&
OBJ_DEFINE_PROPERTY(ccx, obj, id, OBJECT_TO_JSVAL(funobj),
nsnull, nsnull, flags, nsnull);
return NS_OK;
}
// Define the property on the object
NS_ASSERTION(member->IsProperty(), "way broken!");
flags |= JSPROP_GETTER | JSPROP_SHARED;
if(member->IsSetter())
{
flags |= JSPROP_SETTER;
flags &= ~JSPROP_READONLY;
}
AutoResolveName arn(ccx, idval);
*retval = JS_ValueToId(ccx, idval, &id) &&
OBJ_DEFINE_PROPERTY(ccx, obj, id, JSVAL_VOID,
(JSPropertyOp) funobj,
(JSPropertyOp) funobj,
flags, nsnull);
return NS_OK;
}
/* PRBool convert (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 type, in JSValPtr vp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::Convert(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
PRUint32 type, jsval * vp,
PRBool *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void finalize (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::Finalize(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRBool checkAccess (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 mode, in JSValPtr vp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::CheckAccess(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
jsval id, PRUint32 mode, jsval * vp,
PRBool *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRBool call (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::Call(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
PRUint32 argc, jsval * argv,
jsval * vp, PRBool *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::Construct(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
PRUint32 argc, jsval * argv,
jsval * vp, PRBool *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::HasInstance(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
jsval val, PRBool *bp,
PRBool *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRUint32 mark (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in voidPtr arg); */
NS_IMETHODIMP
XPCIDispatchScriptableHelper::Mark(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
void * arg, PRUint32 *retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMPL_ISUPPORTS1(XPCIDispatchClassInfo, nsIClassInfo)
XPCIDispatchClassInfo* XPCIDispatchClassInfo::sInstance = nsnull;
@ -78,9 +400,9 @@ XPCIDispatchClassInfo::GetInterfaces(PRUint32 *count, nsIID * **array)
/* nsISupports getHelperForLanguage (in PRUint32 language); */
NS_IMETHODIMP
XPCIDispatchClassInfo::GetHelperForLanguage(PRUint32 language,
nsISupports **_retval)
nsISupports **retval)
{
*_retval = nsnull;
*retval = XPCIDispatchScriptableHelper::GetSingleton();
return NS_OK;
}

View File

@ -148,104 +148,6 @@ JSBool XPCIDispatchExtension::Initialize(JSContext * aJSContext,
return result;
}
JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx,
JSObject *obj, jsval idval,
XPCWrappedNative* wrapperToReflectInterfaceNames,
uintN propFlags, JSBool* resolved)
{
if(!JSVAL_IS_STRING(idval))
return JS_FALSE;
// Look up the native interface for IDispatch and then find a tearoff
XPCNativeInterface* iface = XPCNativeInterface::GetNewOrUsed(ccx,
"IDispatch");
if(iface == nsnull)
return JS_FALSE;
XPCWrappedNativeTearOff* to =
wrapperToReflectInterfaceNames->FindTearOff(ccx, iface, JS_TRUE);
if(to == nsnull)
return JS_FALSE;
// get the JS Object for the tea
JSObject* jso = to->GetJSObject();
if(jso == nsnull)
return JS_FALSE;
// Look up the member in the interface
const XPCDispInterface::Member * member = to->GetIDispatchInfo()->FindMember(idval);
if(!member)
{
// IDispatch is case insensitive, so if we don't find a case sensitive
// match, we'll try a more expensive case-insensisitive search
// TODO: We need to create cleaner solution that doesn't create
// multiple properties of different case on the JS Object
member = to->GetIDispatchInfo()->FindMemberCI(ccx, idval);
if(!member)
return JS_FALSE;
}
// Get the function object
jsval funval;
if(!member->GetValue(ccx, iface, &funval))
return JS_FALSE;
// Protect the jsval
AUTO_MARK_JSVAL(ccx, funval);
// clone a function we can use for this object
JSObject* funobj = JS_CloneFunctionObject(ccx, JSVAL_TO_OBJECT(funval), obj);
if(!funobj)
return JS_FALSE;
jsid id;
// If this is a function or a parameterized property
if(member->IsFunction() || member->IsParameterizedProperty())
{
// define the function on the object
AutoResolveName arn(ccx, idval);
if(resolved)
*resolved = JS_TRUE;
return JS_ValueToId(ccx, idval, &id) &&
OBJ_DEFINE_PROPERTY(ccx, obj, id, OBJECT_TO_JSVAL(funobj),
nsnull, nsnull, propFlags, nsnull);
}
// Define the property on the object
NS_ASSERTION(member->IsProperty(), "way broken!");
propFlags |= JSPROP_GETTER | JSPROP_SHARED;
if(member->IsSetter())
{
propFlags |= JSPROP_SETTER;
propFlags &= ~JSPROP_READONLY;
}
AutoResolveName arn(ccx, idval);
if(resolved)
*resolved = JS_TRUE;
return JS_ValueToId(ccx, idval, &id) &&
OBJ_DEFINE_PROPERTY(ccx, obj, id, JSVAL_VOID,
(JSPropertyOp) funobj,
(JSPropertyOp) funobj,
propFlags, nsnull);
}
JSBool XPCIDispatchExtension::Enumerate(XPCCallContext& ccx, JSObject* obj,
XPCWrappedNative * wrapper)
{
XPCNativeInterface* iface = XPCNativeInterface::GetNewOrUsed(
ccx,&NSID_IDISPATCH);
if(!iface)
return JS_FALSE;
XPCWrappedNativeTearOff* tearoff = wrapper->FindTearOff(ccx, iface);
if(!tearoff)
return JS_FALSE;
XPCDispInterface* pInfo = tearoff->GetIDispatchInfo();
PRUint32 members = pInfo->GetMemberCount();
// Iterate over the members and force the properties to be resolved
for(PRUint32 index = 0; index < members; ++index)
{
const XPCDispInterface::Member & member = pInfo->GetMember(index);
jsval name = member.GetName();
if(!xpc_ForcePropertyResolve(ccx, obj, name))
return JS_FALSE;
}
return JS_TRUE;
}
nsresult XPCIDispatchExtension::IDispatchQIWrappedJS(nsXPCWrappedJS * self,
void ** aInstancePtr)
{

View File

@ -372,15 +372,7 @@ DefinePropertyIfFound(XPCCallContext& ccx,
(JSPropertyOp) funobj, nsnull,
propFlags, nsnull);
}
#ifdef XPC_IDISPATCH_SUPPORT
// Check to see if there's an IDispatch tearoff
if(wrapperToReflectInterfaceNames &&
XPCIDispatchExtension::DefineProperty(ccx, obj,
idval, wrapperToReflectInterfaceNames, propFlags, resolved))
return JS_TRUE;
#endif
if(resolved)
*resolved = JS_FALSE;
return JS_TRUE;
@ -604,13 +596,6 @@ XPC_WN_Shared_Enumerate(JSContext *cx, JSObject *obj)
for(PRUint16 i = 0; i < interface_count; i++)
{
XPCNativeInterface* iface = interfaceArray[i];
#ifdef XPC_IDISPATCH_SUPPORT
if(iface->GetIID()->Equals(NSID_IDISPATCH))
{
XPCIDispatchExtension::Enumerate(ccx, obj, wrapper);
continue;
}
#endif
PRUint16 member_count = iface->GetMemberCount();
for(PRUint16 k = 0; k < member_count; k++)
{