NOT YET PART OF SEAMONKEY - more conversion stuff implemented

This commit is contained in:
jband%netscape.com 1999-02-13 19:28:38 +00:00
Родитель 50b4c17f6d
Коммит b65de451d8
11 изменённых файлов: 288 добавлений и 144 удалений

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

@ -1 +1,4 @@
Makefile Makefile
convert
mk.bat
set_env.bat

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

@ -83,6 +83,25 @@ nsXPConnect::GetInterfaceInfoManager(nsXPConnect* xpc /*= NULL*/)
return iim; return iim;
} }
// static
XPCContext*
nsXPConnect::GetContext(JSContext* cx, nsXPConnect* xpc /*= NULL*/)
{
NS_PRECONDITION(cx,"bad param");
XPCContext* xpcc;
nsXPConnect* xpcl = xpc;
if(!xpcl && !(xpcl = GetXPConnect()))
return NULL;
xpcc = xpcl->mContextMap->Find(cx);
if(!xpcc)
xpcc = xpcl->NewContext(cx, JS_GetGlobalObject(cx));
if(!xpc)
NS_RELEASE(xpcl);
return xpcc;
}
nsXPConnect::nsXPConnect() nsXPConnect::nsXPConnect()
: mContextMap(NULL), : mContextMap(NULL),
mAllocator(NULL), mAllocator(NULL),
@ -130,17 +149,6 @@ nsXPConnect::InitJSContext(JSContext* aJSContext,
return NS_OK; return NS_OK;
} }
XPCContext*
nsXPConnect::GetContext(JSContext* cx)
{
XPCContext* xpcc;
NS_PRECONDITION(cx,"bad param");
xpcc = mContextMap->Find(cx);
if(!xpcc)
xpcc = NewContext(cx, JS_GetGlobalObject(cx));
return xpcc;
}
XPCContext* XPCContext*
nsXPConnect::NewContext(JSContext* cx, JSObject* global) nsXPConnect::NewContext(JSContext* cx, JSObject* global)
{ {
@ -171,7 +179,7 @@ nsXPConnect::WrapNative(JSContext* aJSContext,
*aWrapper = NULL; *aWrapper = NULL;
XPCContext* xpcc = GetContext(aJSContext); XPCContext* xpcc = nsXPConnect::GetContext(aJSContext, this);
if(!xpcc) if(!xpcc)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -197,7 +205,7 @@ nsXPConnect::WrapJS(JSContext* aJSContext,
*aWrapper = NULL; *aWrapper = NULL;
XPCContext* xpcc = GetContext(aJSContext); XPCContext* xpcc = nsXPConnect::GetContext(aJSContext, this);
if(!xpcc) if(!xpcc)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;

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

@ -20,6 +20,8 @@
#include "xpcprivate.h" #include "xpcprivate.h"
static NS_DEFINE_IID(kWrappedJSMethodsIID, NS_IXPCONNECT_WRAPPED_JS_METHODS_IID);
// static // static
JSBool JSBool
XPCConvert::IsMethodReflectable(const nsXPTMethodInfo& info) XPCConvert::IsMethodReflectable(const nsXPTMethodInfo& info)
@ -180,8 +182,8 @@ XPCConvert::IsMethodReflectable(const nsXPTMethodInfo& info)
// static // static
JSBool JSBool
XPCConvert::NativeData2JS(jsval* d, const void* s, XPCConvert::NativeData2JS(JSContext* cx, jsval* d, const void* s,
const nsXPTType& type) const nsXPTType& type, const nsID* iid)
{ {
NS_PRECONDITION(s, "bad param"); NS_PRECONDITION(s, "bad param");
NS_PRECONDITION(d, "bad param"); NS_PRECONDITION(d, "bad param");
@ -209,40 +211,96 @@ XPCConvert::NativeData2JS(jsval* d, const void* s,
NS_ASSERTION(0,"unsupported type"); NS_ASSERTION(0,"unsupported type");
return JS_FALSE; return JS_FALSE;
} }
// set the default result
*d = JSVAL_NULL;
switch(type.TagPart()) switch(type.TagPart())
{ {
case nsXPTType::T_VOID: case nsXPTType::T_VOID:
// XXX implement void* // XXX implement void* ?
NS_ASSERTION(0,"void* params not supported"); NS_ASSERTION(0,"void* params not supported");
return JS_FALSE; return JS_FALSE;
case nsXPTType::T_IID: case nsXPTType::T_IID:
// XXX implement IID {
NS_ASSERTION(0,"iid params not supported"); nsID* iid = *((nsID**)s);
return JS_FALSE; if(!iid)
break;
JSObject* obj;
if(!(obj = xpc_NewIDObject(cx, *iid)))
break;
*d = OBJECT_TO_JSVAL(obj);
break;
}
case nsXPTType::T_BSTR: case nsXPTType::T_BSTR:
// XXX implement BSTR // XXX implement BSTR ?
NS_ASSERTION(0,"string params not supported"); NS_ASSERTION(0,"'BSTR' string params not supported");
return JS_FALSE; return JS_FALSE;
case nsXPTType::T_CHAR_STR: case nsXPTType::T_CHAR_STR:
// XXX implement CHAR_STR {
NS_ASSERTION(0,"string params not supported"); char* p = *((char**)s);
return JS_FALSE; if(!p)
break;
JSString* str;
if(!(str = JS_NewStringCopyZ(cx, p)))
break;
*d = STRING_TO_JSVAL(str);
break;
}
case nsXPTType::T_WCHAR_STR: case nsXPTType::T_WCHAR_STR:
// XXX implement WCHAR_STR {
NS_ASSERTION(0,"string params not supported"); jschar* p = *((jschar**)s);
return JS_FALSE; if(!p)
break;
JSString* str;
if(!(str = JS_NewUCStringCopyZ(cx, p)))
break;
*d = STRING_TO_JSVAL(str);
break;
}
case nsXPTType::T_INTERFACE: case nsXPTType::T_INTERFACE:
// XXX implement INTERFACE
// make sure 'src' is an object
// get the nsIInterfaceInfo* from the param and
// build a wrapper and then hand over the wrapper.
// XXX remember to release the wrapper in cleanup below
NS_ASSERTION(0,"interface params not supported");
return JS_FALSE;
case nsXPTType::T_INTERFACE_IS: case nsXPTType::T_INTERFACE_IS:
// XXX implement INTERFACE_IS {
NS_ASSERTION(0,"interface_is params not supported"); nsISupports* iface = *((nsISupports**)s);
return JS_FALSE; if(!iface)
break;
JSObject* aJSObj;
// is this a wrapped JS object?
if(nsXPCWrappedJSClass::IsWrappedJS(iface))
{
nsIXPConnectWrappedJSMethods* methods;
if(NS_SUCCEEDED(iface->QueryInterface(kWrappedJSMethodsIID,
(void**)&methods)) &&
NS_SUCCEEDED(methods->GetJSObject(&aJSObj)))
{
NS_RELEASE(methods);
*d = OBJECT_TO_JSVAL(aJSObj);
}
}
else
{
// we need to build a wrapper
nsXPCWrappedNative* wrapper;
XPCContext* xpcc;
if(!iid || !(xpcc = nsXPConnect::GetContext(cx)) ||
!(wrapper = nsXPCWrappedNative::GetNewOrUsedWrapper(xpcc,
iface, *iid)))
{
break;
}
aJSObj = wrapper->GetJSObject();
NS_RELEASE(wrapper);
if(aJSObj)
*d = OBJECT_TO_JSVAL(aJSObj);
}
break;
}
default: default:
NS_ASSERTION(0, "bad type"); NS_ASSERTION(0, "bad type");
return JS_FALSE; return JS_FALSE;
@ -430,17 +488,47 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
} }
case nsXPTType::T_INTERFACE: case nsXPTType::T_INTERFACE:
// XXX implement INTERFACE
// make sure 'src' is an object
// get the nsIInterfaceInfo* from the param and
// build a wrapper and then hand over the wrapper.
// XXX remember to release the wrapper in cleanup below
NS_ASSERTION(0,"interface params not supported");
return JS_FALSE;
case nsXPTType::T_INTERFACE_IS: case nsXPTType::T_INTERFACE_IS:
// XXX implement INTERFACE_IS {
NS_ASSERTION(0,"interface_is params not supported"); NS_ASSERTION(iid,"can't do interface conversions without iid");
JSObject* obj;
nsISupports* iface = NULL;
// only wrpa JSObjects
if(!JSVAL_IS_OBJECT(s) ||
(!(obj = JSVAL_TO_OBJECT(s))))
{
// XXX should report error
return JS_FALSE;
}
// is this really a native xpcom object with a wrapper?
nsXPCWrappedNative* wrapper;
if(NULL != (wrapper =
nsXPCWrappedNativeClass::GetWrappedNativeOfJSObject(cx,obj)))
{
iface = wrapper->GetNative();
// is the underlying object the right interface?
if(wrapper->GetIID().Equals(*iid))
NS_ADDREF(iface);
else
iface->QueryInterface(*iid, (void**)&iface);
}
else
{
// lets try to build a wrapper around the JSObject
XPCContext* xpcc;
if(NULL != (xpcc = nsXPConnect::GetContext(cx)))
iface = nsXPCWrappedJS::GetNewOrUsedWrapper(xpcc, obj, *iid);
}
if(iface)
{
// one AddRef has already been done
*((nsISupports**)d) = iface;
return JS_TRUE;
}
return JS_FALSE; return JS_FALSE;
}
default: default:
NS_ASSERTION(0, "bad type"); NS_ASSERTION(0, "bad type");
return JS_FALSE; return JS_FALSE;

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

@ -68,8 +68,8 @@ public:
static nsXPConnect* GetXPConnect(); static nsXPConnect* GetXPConnect();
static nsIAllocator* GetAllocator(nsXPConnect* xpc = NULL); static nsIAllocator* GetAllocator(nsXPConnect* xpc = NULL);
static nsIInterfaceInfoManager* GetInterfaceInfoManager(nsXPConnect* xpc = NULL); static nsIInterfaceInfoManager* GetInterfaceInfoManager(nsXPConnect* xpc = NULL);
static XPCContext* GetContext(JSContext* cx, nsXPConnect* xpc = NULL);
XPCContext* GetContext(JSContext* cx);
JSContext2XPCContextMap* GetContextMap() {return mContextMap;} JSContext2XPCContextMap* GetContextMap() {return mContextMap;}
nsIXPCScriptable* GetArbitraryScriptable() {return mArbitraryScriptable;} nsIXPCScriptable* GetArbitraryScriptable() {return mArbitraryScriptable;}
@ -144,26 +144,6 @@ class nsIXPCWrappedJSClass : public nsISupports
/*************************/ /*************************/
// nsXPCWrappedJSClass maintains an array of these things
class XPCJSMemberDescriptor
{
private:
enum {
// these are all bitwise flags!
JSMD_REFLECTABLE = 0x1
};
public:
JSBool IsReflectable() const {return flags & JSMD_REFLECTABLE;}
void SetReflectable(JSBool b) {if(b) flags |= JSMD_REFLECTABLE;
else flags &= ~JSMD_REFLECTABLE;}
XPCJSMemberDescriptor(){}
private:
uint16 flags;
};
/*************************/
class nsXPCWrappedJSClass : public nsIXPCWrappedJSClass class nsXPCWrappedJSClass : public nsIXPCWrappedJSClass
{ {
// all the interface method declarations... // all the interface method declarations...
@ -177,7 +157,7 @@ public:
nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;} nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
static JSBool InitForContext(XPCContext* xpcc); static JSBool InitForContext(XPCContext* xpcc);
JSBool IsWrappedJS(nsISupports* aPtr); static JSBool IsWrappedJS(nsISupports* aPtr);
NS_IMETHOD DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID, NS_IMETHOD DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID,
void** aInstancePtr); void** aInstancePtr);
@ -351,7 +331,8 @@ public:
const XPCNativeMemberDescriptor* LookupMemberByID(jsid id) const; const XPCNativeMemberDescriptor* LookupMemberByID(jsid id) const;
JSBool GetConstantAsJSVal(nsXPCWrappedNative* wrapper, JSBool GetConstantAsJSVal(JSContext* cx,
nsXPCWrappedNative* wrapper,
const XPCNativeMemberDescriptor* desc, const XPCNativeMemberDescriptor* desc,
jsval* vp); jsval* vp);
@ -409,15 +390,6 @@ private:
/*************************/ /*************************/
class nsXPCArbitraryScriptable : public nsIXPCScriptable
{
public:
// all the interface method declarations...
NS_DECL_ISUPPORTS;
XPC_DECLARE_IXPCSCRIPTABLE;
nsXPCArbitraryScriptable() {NS_INIT_REFCNT();NS_ADDREF_THIS();}
};
class nsXPCWrappedNative : public nsIXPConnectWrappedNative class nsXPCWrappedNative : public nsIXPConnectWrappedNative
{ {
// all the interface method declarations... // all the interface method declarations...
@ -465,6 +437,17 @@ private:
nsXPCWrappedNative* mNext; nsXPCWrappedNative* mNext;
}; };
/***************************************************************************/
class nsXPCArbitraryScriptable : public nsIXPCScriptable
{
public:
// all the interface method declarations...
NS_DECL_ISUPPORTS;
XPC_DECLARE_IXPCSCRIPTABLE;
nsXPCArbitraryScriptable() {NS_INIT_REFCNT();NS_ADDREF_THIS();}
};
/***************************************************************************/ /***************************************************************************/
// nsID JavaScript class functions // nsID JavaScript class functions
@ -486,8 +469,8 @@ class XPCConvert
public: public:
static JSBool IsMethodReflectable(const nsXPTMethodInfo& info); static JSBool IsMethodReflectable(const nsXPTMethodInfo& info);
static JSBool NativeData2JS(jsval* d, const void* s, static JSBool NativeData2JS(JSContext* cx, jsval* d, const void* s,
const nsXPTType& type); const nsXPTType& type, const nsID* iid);
static JSBool JSData2Native(JSContext* cx, void* d, jsval s, static JSBool JSData2Native(JSContext* cx, void* d, jsval s,
const nsXPTType& type, const nsXPTType& type,

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

@ -57,13 +57,15 @@ struct nsXPCVariant : public nsXPCMiniVariant
enum enum
{ {
PTR_IS_DATA = 0x1, // used for OUT params of Arithmetic types, // these are bitflags!
// ptr points to data in val PTR_IS_DATA = 0x1, // ptr points to 'real' data in val
VAL_IS_OWNED = 0x2 // val.p holds an alloced ptr that must be freed VAL_IS_OWNED = 0x2, // val.p holds alloced ptr that must be freed
VAL_IS_IFACE = 0x4 // val.p holds interface ptr that must be released
}; };
JSBool IsPtrData() const {return (JSBool) (flags & PTR_IS_DATA);} JSBool IsPtrData() const {return (JSBool) (flags & PTR_IS_DATA);}
JSBool IsValOwned() const {return (JSBool) (flags & VAL_IS_OWNED);} JSBool IsValOwned() const {return (JSBool) (flags & VAL_IS_OWNED);}
JSBool IsValInterface() const {return (JSBool) (flags & VAL_IS_IFACE);}
}; };
#endif /* xpcvariant_h___ */ #endif /* xpcvariant_h___ */

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

@ -195,6 +195,7 @@ public:
/***************************************************************************/ /***************************************************************************/
// static
JSBool JSBool
nsXPCWrappedJSClass::IsWrappedJS(nsISupports* aPtr) nsXPCWrappedJSClass::IsWrappedJS(nsISupports* aPtr)
{ {
@ -317,7 +318,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
if(type.IsPointer()) if(type.IsPointer())
pv = (nsXPCMiniVariant*) pv->val.p; pv = (nsXPCMiniVariant*) pv->val.p;
if(!XPCConvert::NativeData2JS(&val, &pv->val, type)) if(!XPCConvert::NativeData2JS(cx, &val, &pv->val, type, NULL))
{ {
retval = NS_ERROR_FAILURE; retval = NS_ERROR_FAILURE;
goto done; goto done;

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

@ -307,7 +307,8 @@ nsXPCWrappedNativeClass::GetInterfaceName()
} }
JSBool JSBool
nsXPCWrappedNativeClass::GetConstantAsJSVal(nsXPCWrappedNative* wrapper, nsXPCWrappedNativeClass::GetConstantAsJSVal(JSContext *cx,
nsXPCWrappedNative* wrapper,
const XPCNativeMemberDescriptor* desc, const XPCNativeMemberDescriptor* desc,
jsval* vp) jsval* vp)
{ {
@ -328,7 +329,8 @@ nsXPCWrappedNativeClass::GetConstantAsJSVal(nsXPCWrappedNative* wrapper,
v.type = constant->GetType(); v.type = constant->GetType();
memcpy(&v.val, &mv.val, sizeof(mv.val)); memcpy(&v.val, &mv.val, sizeof(mv.val));
return XPCConvert::NativeData2JS(vp, &v.val, v.type); // XXX if iid consts are supported, then coditionally fill it in here
return XPCConvert::NativeData2JS(cx, vp, &v.val, v.type, NULL);
} }
void void
@ -443,8 +445,12 @@ nsXPCWrappedNativeClass::CallWrappedMethod(nsXPCWrappedNative* wrapper,
if(!param.IsIn()) if(!param.IsIn())
continue; continue;
// in the future there may be a param flag indicating 'stingy'
if(type.IsPointer()) if(type.IsPointer())
{
conditional_al = al; conditional_al = al;
dp->flags |= nsXPCVariant::VAL_IS_OWNED;
}
} }
else else
{ {
@ -458,11 +464,30 @@ nsXPCWrappedNativeClass::CallWrappedMethod(nsXPCWrappedNative* wrapper,
if(type.TagPart() == nsXPTType::T_INTERFACE) if(type.TagPart() == nsXPTType::T_INTERFACE)
{ {
// XXX get the iid dp->flags |= nsXPCVariant::VAL_IS_IFACE;
if(!(conditional_iid = param.GetInterfaceIID()))
{
// XXX this (and others!) should throw rather than report error
ReportError(desc, "could not get interface type");
goto done;
}
} }
else if(type.TagPart() == nsXPTType::T_INTERFACE_IS) else if(type.TagPart() == nsXPTType::T_INTERFACE_IS)
{ {
// XXX get the iid dp->flags |= nsXPCVariant::VAL_IS_IFACE;
uint8 arg_num = param.GetInterfaceIsArgNumber();
const nsXPTParamInfo& param = info->GetParam(arg_num);
const nsXPTType& type = param.GetType();
if(!type.IsPointer() || type.TagPart() != nsXPTType::T_IID ||
!XPCConvert::JSData2Native(cx, &conditional_iid, argv[arg_num],
type, NULL, NULL))
{
// XXX this (and others!) should throw rather than report error
ReportError(desc, "could not get interface type");
goto done;
}
} }
if(!XPCConvert::JSData2Native(cx, &dp->val, src, type, if(!XPCConvert::JSData2Native(cx, &dp->val, src, type,
@ -489,13 +514,38 @@ nsXPCWrappedNativeClass::CallWrappedMethod(nsXPCWrappedNative* wrapper,
{ {
const nsXPTParamInfo& param = info->GetParam(i); const nsXPTParamInfo& param = info->GetParam(i);
const nsXPTType& type = param.GetType(); const nsXPTType& type = param.GetType();
nsID* conditional_iid = NULL;
nsXPCVariant* dp = &dispatchParams[i]; nsXPCVariant* dp = &dispatchParams[i];
if(param.IsOut()) if(param.IsOut())
{ {
jsval v; jsval v;
if(!XPCConvert::NativeData2JS(&v, &dp->val, type)) if(type.TagPart() == nsXPTType::T_INTERFACE)
{
if(!(conditional_iid = param.GetInterfaceIID()))
{
// XXX this (and others!) should throw rather than report error
ReportError(desc, "could not get interface type");
goto done;
}
}
else if(type.TagPart() == nsXPTType::T_INTERFACE_IS)
{
uint8 arg_num = param.GetInterfaceIsArgNumber();
const nsXPTParamInfo& param = info->GetParam(arg_num);
const nsXPTType& type = param.GetType();
if(!type.IsPointer() || type.TagPart() != nsXPTType::T_IID ||
!(conditional_iid = (nsID*)dispatchParams[arg_num].val.p))
{
// XXX this (and others!) should throw rather than report error
ReportError(desc, "could not get interface type");
goto done;
}
}
if(!XPCConvert::NativeData2JS(cx, &v, &dp->val, type,
conditional_iid))
{ {
retval = NS_ERROR_FAILURE; retval = NS_ERROR_FAILURE;
goto done; goto done;
@ -524,12 +574,11 @@ done:
{ {
nsXPCVariant* dp = &dispatchParams[i]; nsXPCVariant* dp = &dispatchParams[i];
void* p = dp->val.p; void* p = dp->val.p;
// XXX verify that ALL this this stuff is right
if(!p) if(!p)
continue; continue;
if(dp->flags & nsXPCVariant::VAL_IS_OWNED) if(dp->IsValOwned() && al)
delete [] p; al->Free(p);
else if(info->GetParam(i).GetType() == nsXPTType::T_INTERFACE) if(dp->IsValInterface())
((nsISupports*)p)->Release(); ((nsISupports*)p)->Release();
} }
@ -619,7 +668,7 @@ WrappedNative_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
if(desc) if(desc)
{ {
if(desc->IsConstant()) if(desc->IsConstant())
return clazz->GetConstantAsJSVal(wrapper, desc, vp); return clazz->GetConstantAsJSVal(cx, wrapper, desc, vp);
else if(desc->IsMethod()) else if(desc->IsMethod())
{ {
// allow for lazy creation of 'prototypical' function invoke object // allow for lazy creation of 'prototypical' function invoke object

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

@ -168,6 +168,13 @@ nsXPTParamInfo::GetInterface() const
return info; return info;
} }
nsIID*
nsXPTParamInfo::GetInterfaceIID() const
{
NS_PRECONDITION(GetType() == nsXPTType::T_INTERFACE,"not an interface");
return &InterfaceDirectoryEntryTable[type.type.interface].iid;
}
/***************************************************************************/ /***************************************************************************/
// VERY simple implementations... // VERY simple implementations...

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

@ -117,6 +117,9 @@ public:
// find (or build) the appropriate nsIInterfaceInfo. Simple :) // find (or build) the appropriate nsIInterfaceInfo. Simple :)
nsIInterfaceInfo* GetInterface() const ; nsIInterfaceInfo* GetInterface() const ;
// a *little* simpler than the above
nsIID* GetInterfaceIID() const ;
private: private:
nsXPTParamInfo(); // no implementation nsXPTParamInfo(); // no implementation
// NO DATA - this a flyweight wrapper // NO DATA - this a flyweight wrapper