NOT PART OF SEAMONKEY - initial stuff for calling from native to JS (works with int params and hardcoded InterfaceInfo). quick implementation of nsID for JavaScript

git-svn-id: svn://10.0.0.236/trunk@17662 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
jband%netscape.com 1999-01-13 22:45:12 +00:00
parent 94275ccb6c
commit f2d2484bc9
18 changed files with 2231 additions and 222 deletions

View File

@ -0,0 +1,55 @@
#!/usr/local/bin/perl
# This is used to generate entry points for WrappedJS. We generate a file to
# be included in the declaraion and a file to be used for expanding macros
# to represent the implementation of the stubs.
$entry_count = 256;
$sentinel_count = 10;
$decl_name = "xpcstubsdecl.inc";
$def_name = "xpcstubsdef.inc";
##
## Write the declarations include file
##
die "Can't open $decl_name" if !open(OUTFILE, ">$decl_name");
print OUTFILE "// generated file - DO NOT EDIT \n\n";
print OUTFILE "// includes ",$entry_count," stub entries, and ",
$sentinel_count," sentinel entries\n\n";
print OUTFILE "// declarations of normal stubs...\n";
print OUTFILE "// 0 is QueryInterface\n";
print OUTFILE "// 1 is AddRef\n";
print OUTFILE "// 2 is Release\n";
for($i = 0; $i < $entry_count; $i++) {
print OUTFILE "NS_IMETHOD Stub",$i+3,"();\n";
}
print OUTFILE "\n// declarations of sentinel stubs\n";
for($i = 0; $i < $sentinel_count; $i++) {
print OUTFILE "NS_IMETHOD Sentinel",$i,"();\n";
}
close(OUTFILE);
##
## Write the definitions include file. This assumes a macro will be used to
## expand the entries written...
##
die "Can't open $def_name" if !open(OUTFILE, ">$def_name");
print OUTFILE "// generated file - DO NOT EDIT \n\n";
print OUTFILE "// includes ",$entry_count," stub entries, and ",
$sentinel_count," sentinel entries\n\n";
for($i = 0; $i < $entry_count; $i++) {
print OUTFILE "STUB_ENTRY(",$i+3,")\n";
}
for($i = 0; $i < $sentinel_count; $i++) {
print OUTFILE "SENTINEL_ENTRY(",$i,")\n";
}

View File

@ -31,11 +31,15 @@ REQUIRES=xpcom js
DEFINES=-DWIN32_LEAN_AND_MEAN -DEXPORT_XPC_API
OBJS= \
.\$(OBJDIR)\xpcnsid.obj \
.\$(OBJDIR)\xpcstubs.obj \
.\$(OBJDIR)\xpcmaps.obj \
.\$(OBJDIR)\xpccontext.obj \
.\$(OBJDIR)\xpcbogusjs.obj \
.\$(OBJDIR)\xpcbogusii.obj \
.\$(OBJDIR)\xpcinvoke.obj \
.\$(OBJDIR)\xpcwrappedjs.obj \
.\$(OBJDIR)\xpcwrappedjsclass.obj \
.\$(OBJDIR)\xpcwrappednative.obj \
.\$(OBJDIR)\xpcwrappednativeclass.obj \
.\$(OBJDIR)\nsXPConnect.obj \

View File

@ -170,7 +170,7 @@ XPC_NewJSObject(nsIJSContext* aJSContext, JSObject* jsobj);
#ifdef DEBUG
// XXX temprary forawrd declaration
class nsXPCVarient;
struct nsXPCVarient;
XPC_PUBLIC_API(nsresult)
XPC_TestInvoke(void* that, PRUint32 index,
uint32 paramCount, nsXPCVarient* params);

View File

@ -156,7 +156,34 @@ nsXPConnect::WrapJS(nsIJSContext* aJSContext,
REFNSIID aIID,
nsIXPConnectWrappedJS** aWrapper)
{
// XXX implement...
NS_PRECONDITION(aJSContext,"bad param");
NS_PRECONDITION(aJSObj,"bad param");
NS_PRECONDITION(aWrapper,"bad param");
*aWrapper = NULL;
JSObject* jsobj;
if(NS_FAILED(aJSObj->GetNative(&jsobj)) || !jsobj)
{
NS_ASSERTION(0, "bad nsIJSObject*");
return NS_ERROR_FAILURE;
}
JSContext* cx;
if(NS_FAILED(aJSContext->GetNative(&cx)))
return NS_ERROR_FAILURE;
XPCContext* xpcc = GetContext(cx);
if(!xpcc)
return NS_ERROR_FAILURE;
nsXPCWrappedJS* wrapper =
nsXPCWrappedJS::GetNewOrUsedWrapper(xpcc, jsobj, aIID);
if(!wrapper)
return NS_ERROR_FAILURE;
*aWrapper = wrapper;
return NS_OK;
}
@ -213,5 +240,8 @@ nsXPConnect::GetNativeOfWrappedNative(nsIXPConnectWrappedNative* aWrapper,
XPC_PUBLIC_API(nsIXPConnect*)
XPC_GetXPConnect()
{
// temp test...
// nsXPCWrappedJS* p = new nsXPCWrappedJS();
// p->Stub5();
return nsXPConnect::GetXPConnect();
}

View File

@ -15,7 +15,7 @@
class nsITestXPCFoo : public nsISupports
{
public:
NS_IMETHOD Test(int p1, int p2) = 0;
NS_IMETHOD Test(int p1, int p2, int* retval) = 0;
NS_IMETHOD Test2() = 0;
};
@ -33,7 +33,7 @@ public:
class nsTestXPCFoo : public nsITestXPCFoo2
{
NS_DECL_ISUPPORTS;
NS_IMETHOD Test(int p1, int p2);
NS_IMETHOD Test(int p1, int p2, int* retval);
NS_IMETHOD Test2();
nsTestXPCFoo();
};
@ -46,9 +46,10 @@ nsresult nsTestXPCFoo::QueryInterface(REFNSIID aIID, void** aInstancePtr)
return NS_OK;
}
nsresult nsTestXPCFoo::Test(int p1, int p2)
nsresult nsTestXPCFoo::Test(int p1, int p2, int* retval)
{
printf("nsTestXPCFoo::Test called with p1 = %d and p2 = %d\n", p1, p2);
*retval = p1+p2;
return NS_OK;
}
nsresult nsTestXPCFoo::Test2()
@ -171,16 +172,40 @@ int main()
JS_SetProperty(cx, glob, "foo", &v);
char* txt[] = {
"print('foo = '+foo)",
"print('foo.five = '+ foo.five)",
"print('foo.six = '+ foo.six)",
"print('foo.bogus = '+ foo.bogus)",
"foo.Test(10,20)",
"print('foo.Test(10,20) returned: '+foo.Test(10,20))",
"function Test(p1, p2){print('test called in JS with p1 = '+p1+' and p2 = '+p2);return p1+p2;}",
"bar = new Object()",
"bar.Test = Test",
// "bar.Test(5,7)",
"function QI(iid){print('QueryInterface called in JS with iid = '+iid); return this;}",
"bar.QueryInterface = QI",
0,
};
for(char** p = txt; *p; p++)
JS_EvaluateScript(cx, glob, *p, strlen(*p), "builtin", 1, &rval);
if(JS_GetProperty(cx, glob, "bar", &v) && JSVAL_IS_OBJECT(v))
{
JSObject* bar = JSVAL_TO_OBJECT(v);
nsIXPConnectWrappedJS* wrapper;
if(NS_SUCCEEDED(xpc->WrapJS(xpccx,
XPC_NewJSObject(xpccx, JSVAL_TO_OBJECT(v)),
kIFooIID, &wrapper)))
{
nsITestXPCFoo* ptr = (nsITestXPCFoo*)wrapper;
int result;
ptr->Test(11, 13, &result);
printf("call to ptr->Test returned %d\n", result);
NS_RELEASE(wrapper);
}
}
NS_RELEASE(obj);
NS_RELEASE(com_obj);

View File

@ -46,9 +46,10 @@ nsInterfaceInfo::nsInterfaceInfo(REFNSIID aIID, const char* aName,
mMethodCount = 4;
mMethods = new nsXPCMethodInfo[4];
nsXPCParamInfo* params = new nsXPCParamInfo[2];
nsXPCParamInfo* params = new nsXPCParamInfo[3];
params[0] = nsXPCParamInfo(nsXPCParamInfo::IS_IN, nsXPCType::T_I32);
params[1] = nsXPCParamInfo(nsXPCParamInfo::IS_IN, nsXPCType::T_I32);
params[2] = nsXPCParamInfo(nsXPCParamInfo::IS_OUT | nsXPCParamInfo::IS_RETVAL, nsXPCType::T_I32);
nsXPCParamInfo result = nsXPCParamInfo(nsXPCParamInfo::IS_OUT, nsXPCType::T_U32);
// XXX these are bogus declarations - don't call!
@ -56,7 +57,7 @@ nsInterfaceInfo::nsInterfaceInfo(REFNSIID aIID, const char* aName,
mMethods[1] = nsXPCMethodInfo(0, "AddRef", 0, NULL, result);
mMethods[2] = nsXPCMethodInfo(0, "Release", 0, NULL, result);
// this one should be callable (in test/TestXPC.cpp)
mMethods[3] = nsXPCMethodInfo(0, "Test", 2, params, result);
mMethods[3] = nsXPCMethodInfo(0, "Test", 3, params, result);
///////

View File

@ -76,40 +76,13 @@ public:
T_INTERFACE = 16, /* SPECIAL_BIT | 0 */
T_INTERFACE_IS = 17 /* SPECIAL_BIT | 1 */
};
uint8 WordCount() const
{
static uint8 word_table[] =
{
1, // T_I8
1, // T_I16
1, // T_I32
2, // T_I64
1, // T_U8
1, // T_U16
1, // T_U32
2, // T_U64
1, // T_FLOAT
2, // T_DOUBLE
1, // T_BOOL
1, // T_CHAR
1 // T_WCHAR
};
if(t & IS_POINTER)
return 1;
if(t & SPECIAL_BIT)
{
NS_ASSERTION(0,"net yet implemented");
return 1;
}
return word_table[t & TYPE_MASK];
}
};
class nsXPCVarient
// this is used only for WrappedJS stub param repackaging
struct nsXPCMiniVarient
{
public:
// val must come first!
// No ctors or dtors so that we can use arrays of these on the stack
// with no penalty.
union
{
int8 i8;
@ -126,9 +99,45 @@ public:
char c;
wchar_t wc;
void* p;
} val;
} val;
};
struct nsXPCVarient
{
// No ctors or dtors so that we can use arrays of these on the stack
// with no penalty.
union
{
int8 i8;
int16 i16;
int32 i32;
int64 i64;
uint8 u8;
uint16 u16;
uint32 u32;
uint64 u64;
float f;
double d;
PRBool b;
char c;
wchar_t wc;
void* p;
nsID id;
} val;
void* ptr;
void* ptr2;
nsXPCType type;
uint8 flags;
enum
{
PTR_IS_DATA = 0x1, // used for OUT params, ptr points to data in val
VAL_IS_OWNED = 0x2 // val.p holds an alloced ptr that must be freed
};
JSBool IsPtrData() const {return (JSBool) (flags & PTR_IS_DATA);}
JSBool IsValOwned() const {return (JSBool) (flags & VAL_IS_OWNED);}
};

View File

@ -50,6 +50,8 @@ XPCContext::newXPCContext(JSContext* aJSContext,
xpcc->GetWrappedNativeMap() &&
xpcc->GetWrappedJSClassMap() &&
xpcc->GetWrappedNativeClassMap() &&
xpc_InitIDClass(xpcc) &&
nsXPCWrappedJSClass::InitForContext(xpcc) &&
nsXPCWrappedNativeClass::InitForContext(xpcc))
{
return xpcc;

View File

@ -25,12 +25,17 @@
// Remember that on Win32 these 'words' are 32bit DWORDS
static uint32 __stdcall
invoke_count_words(uint32 paramCount, nsXPCVarient* src)
invoke_count_words(uint32 paramCount, nsXPCVarient* s)
{
uint32 result = 0;
for(uint32 i = 0; i < paramCount; i++, src++)
for(uint32 i = 0; i < paramCount; i++, s++)
{
switch(src->type)
if(s->IsPtrData())
{
result++;
continue;
}
switch(s->type)
{
case nsXPCType::T_I8 :
case nsXPCType::T_I16 :
@ -56,7 +61,7 @@ invoke_count_words(uint32 paramCount, nsXPCVarient* src)
result++;
break;
default:
NS_ASSERTION(src->type & nsXPCType::IS_POINTER, "bad type");
NS_ASSERTION(s->type & nsXPCType::IS_POINTER, "bad type");
result++;
break;
}
@ -69,6 +74,11 @@ invoke_copy_to_stack(uint32* d, uint32 paramCount, nsXPCVarient* s)
{
for(uint32 i = 0; i < paramCount; i++, d++, s++)
{
if(s->IsPtrData())
{
*((void**)d) = s->ptr;
continue;
}
switch(s->type)
{
case nsXPCType::T_I8 : *((int8*) d) = s->val.i8; break;

View File

@ -0,0 +1,204 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* Implement the nsID JavaScript class. */
#include "xpcprivate.h"
// IDData hold the private data
class IDData
{
public:
IDData(); // not implemented
IDData(const nsID& aID);
IDData(JSContext *cx, const IDData& r);
~IDData(); // no virtual functions
JSBool GetString(JSContext *cx, jsval *rval);
JSBool Equals(const IDData& r);
void Cleanup(JSContext *cx);
private:
nsID mID;
JSString* mStr;
};
IDData::IDData(const nsID& aID) : mID(aID), mStr(NULL) {}
IDData::IDData(JSContext *cx, const IDData& r) : mID(r.mID), mStr(r.mStr)
{
if(mStr)
JS_AddRoot(cx, &mStr);
}
IDData::~IDData()
{
NS_ASSERTION(!mStr, "deleting IDData without calling Cleanup first");
}
void
IDData::Cleanup(JSContext *cx)
{
if(mStr)
{
JS_RemoveRoot(cx, &mStr);
mStr = NULL;
}
}
JSBool
IDData::GetString(JSContext *cx, jsval *rval)
{
if(!mStr)
{
char* str = mID.ToString();
NS_ASSERTION(str, "nsID.ToString failed");
if(str)
{
if(NULL != (mStr = JS_NewStringCopyZ(cx, str)))
JS_AddRoot(cx, &mStr);
delete [] str;
}
}
*rval = STRING_TO_JSVAL(mStr);
return (JSBool) mStr;
}
JSBool
IDData::Equals(const IDData& r)
{
return (JSBool) mID.Equals(r.mID);
}
/***************************************************************************/
JS_STATIC_DLL_CALLBACK(void)
nsID_finalize(JSContext *cx, JSObject *obj)
{
IDData* data = (IDData*) JS_GetPrivate(cx, obj);
if(data)
{
data->Cleanup(cx);
delete data;
}
}
static JSClass nsID_class = {
"nsID",
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nsID_finalize
};
JS_STATIC_DLL_CALLBACK(JSBool)
nsID_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
IDData* data;
if(!JS_InstanceOf(cx, obj, &nsID_class, NULL) ||
!(data = (IDData*) JS_GetPrivate(cx, obj)))
return JS_FALSE;
return data->GetString(cx, rval);
}
JS_STATIC_DLL_CALLBACK(JSBool)
nsID_equals(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JSObject *obj2;
IDData* data1;
IDData* data2;
if(!JS_InstanceOf(cx, obj, &nsID_class, NULL) ||
!argc || !JSVAL_IS_OBJECT(argv[0]) ||
!(obj2 = JSVAL_TO_OBJECT(argv[0])) ||
!JS_InstanceOf(cx, obj2, &nsID_class, NULL) ||
!(data1 = (IDData*) JS_GetPrivate(cx, obj)) ||
!(data2 = (IDData*) JS_GetPrivate(cx, obj2)))
return JS_FALSE;
return data1->Equals(*data2);
}
static JSFunctionSpec nsID_methods[] = {
{"toString", nsID_toString, 0},
{"equals", nsID_equals, 0},
{0}
};
JS_STATIC_DLL_CALLBACK(JSBool)
nsID_ctor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
IDData* data = NULL;
JSString* str;
nsID id;
if(argc == 0)
{
JS_ReportError(cx, "nsID has no constructor that takes zero arguments");
return JS_FALSE;
}
if(JSVAL_IS_OBJECT(argv[0]) &&
JS_InstanceOf(cx, JSVAL_TO_OBJECT(argv[0]), &nsID_class, NULL))
{
IDData* src = (IDData*)JS_GetPrivate(cx,JSVAL_TO_OBJECT(argv[0]));
if(src)
data = new IDData(cx, *src);
}
else if(NULL != (str = JS_ValueToString(cx, argv[0])) &&
id.Parse(JS_GetStringBytes(str)))
{
data = new IDData(id);
}
if(!data)
{
JS_ReportError(cx, "could not constuct nsID");
return JS_FALSE;
}
if(!JS_IsConstructing(cx))
{
obj = JS_NewObject(cx, &nsID_class, NULL, NULL);
if (!obj)
return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj);
}
JS_SetPrivate(cx, obj, data);
return JS_TRUE;
}
JSBool
xpc_InitIDClass(XPCContext* xpcc)
{
if (!JS_InitClass(xpcc->GetJSContext(), xpcc->GetGlobalObject(),
NULL, &nsID_class, nsID_ctor, 1, NULL, nsID_methods, NULL, NULL))
return JS_FALSE;
return JS_TRUE;
}
JSObject *
xpc_NewIDObject(JSContext *cx, const nsID& aID)
{
JSObject *obj;
obj = JS_NewObject(cx, &nsID_class, NULL, NULL);
if(obj)
JS_SetPrivate(cx, obj, new IDData(aID));
return obj;
}

View File

@ -33,6 +33,7 @@
#include "xpcbogusjs.h"
#include "xpcbogusii.h"
extern const char* XPC_VAL_STR; // 'val' property name for out params
/***************************************************************************/
@ -84,7 +85,7 @@ private:
static nsXPConnect* mSelf;
};
/*************************/
/***************************************************************************/
// XPCContext is mostly a dumb class to hold JSContext specific data and
// maps that let us find wrappers created for the given JSContext.
@ -125,34 +126,98 @@ private:
IID2WrappedNativeClassMap* mWrappedNativeClassMap;
};
/***************************************************************************/
// this interfaces exists so we can refcount nsXPCWrappedJSClass
// {2453EBA0-A9B8-11d2-BA64-00805F8A5DD7}
#define NS_IXPCONNECT_WRAPPED_JS_CLASS_IID \
{ 0x2453eba0, 0xa9b8, 0x11d2, \
{ 0xba, 0x64, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
class nsIXPCWrappedJSClass : public nsISupports
{
// no methods
};
/*************************/
class nsXPCWrappedJSClass : public nsIXPCWrappedJSClass
{
// all the interface method declarations...
NS_DECL_ISUPPORTS;
public:
static nsXPCWrappedJSClass* GetNewOrUsedClass(XPCContext* xpcc,
REFNSIID aIID);
REFNSIID GetIID(){return mIID;}
XPCContext* GetXPCContext() {return mXPCContext;}
nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
static JSBool InitForContext(XPCContext* xpcc);
JSBool IsWrappedJS(nsISupports* aPtr);
nsresult DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID,
void** aInstancePtr);
JSObject* GetRootJSObject(JSObject* aJSObj);
nsresult CallMethod(nsXPCWrappedJS* wrapper,
const nsXPCMethodInfo* info,
nsXPCMiniVarient* params);
~nsXPCWrappedJSClass();
private:
nsXPCWrappedJSClass(); // not implemented
nsXPCWrappedJSClass(XPCContext* xpcc, REFNSIID aIID,
nsIInterfaceInfo* aInfo);
JSContext* GetJSContext() {return mXPCContext->GetJSContext();}
JSObject* CreateIIDJSObject(REFNSIID aIID);
JSObject* NewOutObject();
JSObject* CallQueryInterfaceOnJSObject(JSObject* jsobj, REFNSIID aIID);
private:
XPCContext* mXPCContext;
nsIInterfaceInfo* mInfo;
nsIID mIID;
};
/*************************/
class nsXPCWrappedJS : public nsIXPConnectWrappedJS
{
// our vtbl stubs here...
// XXX implement...
public:
JSObject* GetJSObject(){return NULL;}
nsXPCWrappedJSClass* GetClass() {return NULL;}
NS_DECL_ISUPPORTS;
// include our generated vtbl stub declarations
#include "xpcstubsdecl.inc"
};
static nsXPCWrappedJS* GetNewOrUsedWrapper(XPCContext* xpcc,
JSObject* aJSObj,
REFNSIID aIID);
class nsXPCWrappedJSClass : public nsISupports
{
// XXX implement...
public:
JSObject* GetJSObject() {return mJSObj;}
nsXPCWrappedJSClass* GetClass() {return mClass;}
REFNSIID GetIID() {return GetClass()->GetIID();}
nsXPCWrappedJS* GetRootWrapper() {return mRoot;}
REFNSIID GetIID(){return mIID;}
XPCContext* GetXPCContext() {return mXPCContext;}
virtual ~nsXPCWrappedJS();
private:
nsXPCWrappedJS(); // not implemented
nsXPCWrappedJS(JSObject* aJSObj,
nsXPCWrappedJSClass* aClass,
nsXPCWrappedJS* root);
nsXPCWrappedJS* Find(REFNSIID aIID);
private:
XPCContext* mXPCContext;
nsIID mIID;
JSObject* mJSObj;
nsXPCWrappedJSClass* mClass;
nsXPCWrappedJS* mRoot;
nsXPCWrappedJS* mNext;
};
/*************************/
/***************************************************************************/
// nsXPCWrappedNativeClass maintains an array of these things
struct XPCNativeMemberDescriptor
@ -169,15 +234,13 @@ struct XPCNativeMemberDescriptor
uintN index; /* in InterfaceInfo for const, method, and get */
uintN index2; /* in InterfaceInfo for set */
MemberCategory category;
uintN maxParamCount;
uintN maxScratchWordCount;
XPCNativeMemberDescriptor()
: invokeFuncObj(NULL), id(0),
maxParamCount(-1),
maxScratchWordCount(-1){}
: invokeFuncObj(NULL), id(0){}
};
/*************************/
// this interfaces exists just so we can refcount nsXPCWrappedNativeClass
// {C9E36280-954A-11d2-BA5A-00805F8A5DD7}
#define NS_IXPCONNECT_WRAPPED_NATIVE_CLASS_IID \
@ -189,6 +252,8 @@ class nsIXPCWrappedNativeClass : public nsISupports
// no methods
};
/*************************/
class nsXPCWrappedNativeClass : public nsIXPCWrappedNativeClass
{
// all the interface method declarations...
@ -249,21 +314,6 @@ private:
const char* GetMemberName(const XPCNativeMemberDescriptor* desc) const;
JSContext* GetJSContext() {return mXPCContext->GetJSContext();}
uintN GetMaxParamCount(const XPCNativeMemberDescriptor* desc)
{
if(-1 == desc->maxParamCount)
SetDescriptorCounts(NS_CONST_CAST(XPCNativeMemberDescriptor*,desc));
return desc->maxParamCount;
}
uintN GetMaxScratchWordCount(const XPCNativeMemberDescriptor* desc)
{
if(-1 == desc->maxScratchWordCount)
SetDescriptorCounts(NS_CONST_CAST(XPCNativeMemberDescriptor*,desc));
return desc->maxScratchWordCount;
}
void SetDescriptorCounts(XPCNativeMemberDescriptor* desc);
void ReportError(const XPCNativeMemberDescriptor* desc, const char* msg);
JSBool BuildMemberDescriptors();
void DestroyMemberDescriptors();
@ -276,6 +326,8 @@ private:
XPCNativeMemberDescriptor* mMembers;
};
/*************************/
class nsXPCWrappedNative : public nsIXPConnectWrappedNative
{
// all the interface method declarations...
@ -288,6 +340,7 @@ public:
nsISupports* GetNative() {return mObj;}
JSObject* GetJSObject() {return mJSObj;}
nsXPCWrappedNativeClass* GetClass() {return mClass;}
REFNSIID GetIID() {return GetClass()->GetIID();}
void JSObjectFinalized();
virtual ~nsXPCWrappedNative();
@ -307,7 +360,16 @@ private:
nsXPCWrappedNative* mNext;
};
/************************************************/
/***************************************************************************/
// utility functions
JSBool
xpc_InitIDClass(XPCContext* xpcc);
JSObject*
xpc_NewIDObject(JSContext *cx, const nsID& aID);
/***************************************************************************/
// platform specific method invoker
nsresult

View File

@ -0,0 +1,147 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* Implement shared vtbl methods for WrappedJS. */
#include "xpcprivate.h"
#ifdef WIN32
static nsresult __stdcall
PrepareAndDispatch(nsXPCWrappedJS* self, uint32 methodIndex,
uint32* args, uint32* stackBytesToPop)
{
#define PARAM_BUFFER_COUNT 32
nsXPCMiniVarient paramBuffer[PARAM_BUFFER_COUNT];
nsXPCMiniVarient* dispatchParams = NULL;
nsXPCWrappedJSClass* clazz;
nsIInterfaceInfo* iface_info;
const nsXPCMethodInfo* info;
uint8 paramCount;
uint8 i;
nsresult result = NS_ERROR_FAILURE;
// If anything fails before stackBytesToPop can be set then
// the failure is completely catastrophic!
NS_ASSERTION(self,"no self");
clazz = self->GetClass();
NS_ASSERTION(clazz,"no class");
iface_info = clazz->GetInterfaceInfo();
NS_ASSERTION(iface_info,"no interface info");
iface_info->GetMethodInfo(methodIndex, &info);
NS_ASSERTION(info,"no interface info");
paramCount = info->GetParamCount();
// setup varient array pointer
if(paramCount > PARAM_BUFFER_COUNT)
dispatchParams = new nsXPCMiniVarient[paramCount];
else
dispatchParams = paramBuffer;
NS_ASSERTION(dispatchParams,"no place for params");
uint32* ap = args;
for(i = 0; i < paramCount; i++, ap++)
{
const nsXPCParamInfo& param = info->GetParam(i);
const nsXPCType& type = param.GetType();
nsXPCMiniVarient* dp = &dispatchParams[i];
if(param.IsOut() || (type & nsXPCType::IS_POINTER))
{
dp->val.p = (void*) *ap;
continue;
}
// else
switch(type)
{
case nsXPCType::T_I8 : dp->val.i8 = *((int8*) ap); break;
case nsXPCType::T_I16 : dp->val.i16 = *((int16*) ap); break;
case nsXPCType::T_I32 : dp->val.i32 = *((int32*) ap); break;
case nsXPCType::T_I64 : dp->val.i64 = *((int64*) ap); ap++; break;
case nsXPCType::T_U8 : dp->val.u8 = *((uint8*) ap); break;
case nsXPCType::T_U16 : dp->val.u16 = *((uint16*) ap); break;
case nsXPCType::T_U32 : dp->val.u32 = *((uint32*) ap); break;
case nsXPCType::T_U64 : dp->val.u64 = *((uint64*) ap); ap++; break;
case nsXPCType::T_FLOAT : dp->val.f = *((float*) ap); break;
case nsXPCType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
case nsXPCType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
case nsXPCType::T_CHAR : dp->val.c = *((char*) ap); break;
case nsXPCType::T_WCHAR : dp->val.wc = *((wchar_t*)ap); break;
default:
// XXX deal with other types
NS_ASSERTION(0, "type not yet supported");
break;
}
}
*stackBytesToPop = ((uint32)ap) - ((uint32)args);
result = clazz->CallMethod(self, info, dispatchParams);
if(dispatchParams != paramBuffer)
delete [] dispatchParams;
return result;
}
static __declspec(naked) void SharedStub(void)
{
__asm {
push ebp // set up simple stack frame
mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args
push ecx // make room for a ptr
lea eax, [ebp-4] // pointer to stackBytesToPop
push eax
lea ebx, [ebp+16] // pointer to args
push ebx
mov edx, [ebp+4] // vtbl_index
push edx
mov eax, [ebp+12] // this
push eax
call PrepareAndDispatch
mov edx, [ebp+8] // return address
mov ecx, [ebp-4] // stackBytesToPop
add ecx, 12 // for this, the index, and ret address
mov esp, ebp
pop ebp
add esp, ecx // fix up stack pointer
jmp edx // simulate __stdcall return
}
}
#define STUB_ENTRY(n) \
__declspec(naked) nsresult nsXPCWrappedJS::Stub##n() \
{ __asm push n __asm jmp SharedStub }
#define SENTINEL_ENTRY(n) \
nsresult nsXPCWrappedJS::Sentinel##n() \
{ \
NS_ASSERTION(0,"nsXPCWrappedJS::Sentinel called"); \
return NS_ERROR_NOT_IMPLEMENTED; \
}
#pragma warning(disable : 4035) // OK to have no return value
#include "xpcstubsdef.inc"
#pragma warning(default : 4035) // restore default
#endif

View File

@ -0,0 +1,276 @@
// generated file - DO NOT EDIT
// includes 256 stub entries, and 10 sentinel entries
// declarations of normal stubs...
// 0 is QueryInterface
// 1 is AddRef
// 2 is Release
NS_IMETHOD Stub3();
NS_IMETHOD Stub4();
NS_IMETHOD Stub5();
NS_IMETHOD Stub6();
NS_IMETHOD Stub7();
NS_IMETHOD Stub8();
NS_IMETHOD Stub9();
NS_IMETHOD Stub10();
NS_IMETHOD Stub11();
NS_IMETHOD Stub12();
NS_IMETHOD Stub13();
NS_IMETHOD Stub14();
NS_IMETHOD Stub15();
NS_IMETHOD Stub16();
NS_IMETHOD Stub17();
NS_IMETHOD Stub18();
NS_IMETHOD Stub19();
NS_IMETHOD Stub20();
NS_IMETHOD Stub21();
NS_IMETHOD Stub22();
NS_IMETHOD Stub23();
NS_IMETHOD Stub24();
NS_IMETHOD Stub25();
NS_IMETHOD Stub26();
NS_IMETHOD Stub27();
NS_IMETHOD Stub28();
NS_IMETHOD Stub29();
NS_IMETHOD Stub30();
NS_IMETHOD Stub31();
NS_IMETHOD Stub32();
NS_IMETHOD Stub33();
NS_IMETHOD Stub34();
NS_IMETHOD Stub35();
NS_IMETHOD Stub36();
NS_IMETHOD Stub37();
NS_IMETHOD Stub38();
NS_IMETHOD Stub39();
NS_IMETHOD Stub40();
NS_IMETHOD Stub41();
NS_IMETHOD Stub42();
NS_IMETHOD Stub43();
NS_IMETHOD Stub44();
NS_IMETHOD Stub45();
NS_IMETHOD Stub46();
NS_IMETHOD Stub47();
NS_IMETHOD Stub48();
NS_IMETHOD Stub49();
NS_IMETHOD Stub50();
NS_IMETHOD Stub51();
NS_IMETHOD Stub52();
NS_IMETHOD Stub53();
NS_IMETHOD Stub54();
NS_IMETHOD Stub55();
NS_IMETHOD Stub56();
NS_IMETHOD Stub57();
NS_IMETHOD Stub58();
NS_IMETHOD Stub59();
NS_IMETHOD Stub60();
NS_IMETHOD Stub61();
NS_IMETHOD Stub62();
NS_IMETHOD Stub63();
NS_IMETHOD Stub64();
NS_IMETHOD Stub65();
NS_IMETHOD Stub66();
NS_IMETHOD Stub67();
NS_IMETHOD Stub68();
NS_IMETHOD Stub69();
NS_IMETHOD Stub70();
NS_IMETHOD Stub71();
NS_IMETHOD Stub72();
NS_IMETHOD Stub73();
NS_IMETHOD Stub74();
NS_IMETHOD Stub75();
NS_IMETHOD Stub76();
NS_IMETHOD Stub77();
NS_IMETHOD Stub78();
NS_IMETHOD Stub79();
NS_IMETHOD Stub80();
NS_IMETHOD Stub81();
NS_IMETHOD Stub82();
NS_IMETHOD Stub83();
NS_IMETHOD Stub84();
NS_IMETHOD Stub85();
NS_IMETHOD Stub86();
NS_IMETHOD Stub87();
NS_IMETHOD Stub88();
NS_IMETHOD Stub89();
NS_IMETHOD Stub90();
NS_IMETHOD Stub91();
NS_IMETHOD Stub92();
NS_IMETHOD Stub93();
NS_IMETHOD Stub94();
NS_IMETHOD Stub95();
NS_IMETHOD Stub96();
NS_IMETHOD Stub97();
NS_IMETHOD Stub98();
NS_IMETHOD Stub99();
NS_IMETHOD Stub100();
NS_IMETHOD Stub101();
NS_IMETHOD Stub102();
NS_IMETHOD Stub103();
NS_IMETHOD Stub104();
NS_IMETHOD Stub105();
NS_IMETHOD Stub106();
NS_IMETHOD Stub107();
NS_IMETHOD Stub108();
NS_IMETHOD Stub109();
NS_IMETHOD Stub110();
NS_IMETHOD Stub111();
NS_IMETHOD Stub112();
NS_IMETHOD Stub113();
NS_IMETHOD Stub114();
NS_IMETHOD Stub115();
NS_IMETHOD Stub116();
NS_IMETHOD Stub117();
NS_IMETHOD Stub118();
NS_IMETHOD Stub119();
NS_IMETHOD Stub120();
NS_IMETHOD Stub121();
NS_IMETHOD Stub122();
NS_IMETHOD Stub123();
NS_IMETHOD Stub124();
NS_IMETHOD Stub125();
NS_IMETHOD Stub126();
NS_IMETHOD Stub127();
NS_IMETHOD Stub128();
NS_IMETHOD Stub129();
NS_IMETHOD Stub130();
NS_IMETHOD Stub131();
NS_IMETHOD Stub132();
NS_IMETHOD Stub133();
NS_IMETHOD Stub134();
NS_IMETHOD Stub135();
NS_IMETHOD Stub136();
NS_IMETHOD Stub137();
NS_IMETHOD Stub138();
NS_IMETHOD Stub139();
NS_IMETHOD Stub140();
NS_IMETHOD Stub141();
NS_IMETHOD Stub142();
NS_IMETHOD Stub143();
NS_IMETHOD Stub144();
NS_IMETHOD Stub145();
NS_IMETHOD Stub146();
NS_IMETHOD Stub147();
NS_IMETHOD Stub148();
NS_IMETHOD Stub149();
NS_IMETHOD Stub150();
NS_IMETHOD Stub151();
NS_IMETHOD Stub152();
NS_IMETHOD Stub153();
NS_IMETHOD Stub154();
NS_IMETHOD Stub155();
NS_IMETHOD Stub156();
NS_IMETHOD Stub157();
NS_IMETHOD Stub158();
NS_IMETHOD Stub159();
NS_IMETHOD Stub160();
NS_IMETHOD Stub161();
NS_IMETHOD Stub162();
NS_IMETHOD Stub163();
NS_IMETHOD Stub164();
NS_IMETHOD Stub165();
NS_IMETHOD Stub166();
NS_IMETHOD Stub167();
NS_IMETHOD Stub168();
NS_IMETHOD Stub169();
NS_IMETHOD Stub170();
NS_IMETHOD Stub171();
NS_IMETHOD Stub172();
NS_IMETHOD Stub173();
NS_IMETHOD Stub174();
NS_IMETHOD Stub175();
NS_IMETHOD Stub176();
NS_IMETHOD Stub177();
NS_IMETHOD Stub178();
NS_IMETHOD Stub179();
NS_IMETHOD Stub180();
NS_IMETHOD Stub181();
NS_IMETHOD Stub182();
NS_IMETHOD Stub183();
NS_IMETHOD Stub184();
NS_IMETHOD Stub185();
NS_IMETHOD Stub186();
NS_IMETHOD Stub187();
NS_IMETHOD Stub188();
NS_IMETHOD Stub189();
NS_IMETHOD Stub190();
NS_IMETHOD Stub191();
NS_IMETHOD Stub192();
NS_IMETHOD Stub193();
NS_IMETHOD Stub194();
NS_IMETHOD Stub195();
NS_IMETHOD Stub196();
NS_IMETHOD Stub197();
NS_IMETHOD Stub198();
NS_IMETHOD Stub199();
NS_IMETHOD Stub200();
NS_IMETHOD Stub201();
NS_IMETHOD Stub202();
NS_IMETHOD Stub203();
NS_IMETHOD Stub204();
NS_IMETHOD Stub205();
NS_IMETHOD Stub206();
NS_IMETHOD Stub207();
NS_IMETHOD Stub208();
NS_IMETHOD Stub209();
NS_IMETHOD Stub210();
NS_IMETHOD Stub211();
NS_IMETHOD Stub212();
NS_IMETHOD Stub213();
NS_IMETHOD Stub214();
NS_IMETHOD Stub215();
NS_IMETHOD Stub216();
NS_IMETHOD Stub217();
NS_IMETHOD Stub218();
NS_IMETHOD Stub219();
NS_IMETHOD Stub220();
NS_IMETHOD Stub221();
NS_IMETHOD Stub222();
NS_IMETHOD Stub223();
NS_IMETHOD Stub224();
NS_IMETHOD Stub225();
NS_IMETHOD Stub226();
NS_IMETHOD Stub227();
NS_IMETHOD Stub228();
NS_IMETHOD Stub229();
NS_IMETHOD Stub230();
NS_IMETHOD Stub231();
NS_IMETHOD Stub232();
NS_IMETHOD Stub233();
NS_IMETHOD Stub234();
NS_IMETHOD Stub235();
NS_IMETHOD Stub236();
NS_IMETHOD Stub237();
NS_IMETHOD Stub238();
NS_IMETHOD Stub239();
NS_IMETHOD Stub240();
NS_IMETHOD Stub241();
NS_IMETHOD Stub242();
NS_IMETHOD Stub243();
NS_IMETHOD Stub244();
NS_IMETHOD Stub245();
NS_IMETHOD Stub246();
NS_IMETHOD Stub247();
NS_IMETHOD Stub248();
NS_IMETHOD Stub249();
NS_IMETHOD Stub250();
NS_IMETHOD Stub251();
NS_IMETHOD Stub252();
NS_IMETHOD Stub253();
NS_IMETHOD Stub254();
NS_IMETHOD Stub255();
NS_IMETHOD Stub256();
NS_IMETHOD Stub257();
NS_IMETHOD Stub258();
// declarations of sentinel stubs
NS_IMETHOD Sentinel0();
NS_IMETHOD Sentinel1();
NS_IMETHOD Sentinel2();
NS_IMETHOD Sentinel3();
NS_IMETHOD Sentinel4();
NS_IMETHOD Sentinel5();
NS_IMETHOD Sentinel6();
NS_IMETHOD Sentinel7();
NS_IMETHOD Sentinel8();
NS_IMETHOD Sentinel9();

View File

@ -0,0 +1,270 @@
// generated file - DO NOT EDIT
// includes 256 stub entries, and 10 sentinel entries
STUB_ENTRY(3)
STUB_ENTRY(4)
STUB_ENTRY(5)
STUB_ENTRY(6)
STUB_ENTRY(7)
STUB_ENTRY(8)
STUB_ENTRY(9)
STUB_ENTRY(10)
STUB_ENTRY(11)
STUB_ENTRY(12)
STUB_ENTRY(13)
STUB_ENTRY(14)
STUB_ENTRY(15)
STUB_ENTRY(16)
STUB_ENTRY(17)
STUB_ENTRY(18)
STUB_ENTRY(19)
STUB_ENTRY(20)
STUB_ENTRY(21)
STUB_ENTRY(22)
STUB_ENTRY(23)
STUB_ENTRY(24)
STUB_ENTRY(25)
STUB_ENTRY(26)
STUB_ENTRY(27)
STUB_ENTRY(28)
STUB_ENTRY(29)
STUB_ENTRY(30)
STUB_ENTRY(31)
STUB_ENTRY(32)
STUB_ENTRY(33)
STUB_ENTRY(34)
STUB_ENTRY(35)
STUB_ENTRY(36)
STUB_ENTRY(37)
STUB_ENTRY(38)
STUB_ENTRY(39)
STUB_ENTRY(40)
STUB_ENTRY(41)
STUB_ENTRY(42)
STUB_ENTRY(43)
STUB_ENTRY(44)
STUB_ENTRY(45)
STUB_ENTRY(46)
STUB_ENTRY(47)
STUB_ENTRY(48)
STUB_ENTRY(49)
STUB_ENTRY(50)
STUB_ENTRY(51)
STUB_ENTRY(52)
STUB_ENTRY(53)
STUB_ENTRY(54)
STUB_ENTRY(55)
STUB_ENTRY(56)
STUB_ENTRY(57)
STUB_ENTRY(58)
STUB_ENTRY(59)
STUB_ENTRY(60)
STUB_ENTRY(61)
STUB_ENTRY(62)
STUB_ENTRY(63)
STUB_ENTRY(64)
STUB_ENTRY(65)
STUB_ENTRY(66)
STUB_ENTRY(67)
STUB_ENTRY(68)
STUB_ENTRY(69)
STUB_ENTRY(70)
STUB_ENTRY(71)
STUB_ENTRY(72)
STUB_ENTRY(73)
STUB_ENTRY(74)
STUB_ENTRY(75)
STUB_ENTRY(76)
STUB_ENTRY(77)
STUB_ENTRY(78)
STUB_ENTRY(79)
STUB_ENTRY(80)
STUB_ENTRY(81)
STUB_ENTRY(82)
STUB_ENTRY(83)
STUB_ENTRY(84)
STUB_ENTRY(85)
STUB_ENTRY(86)
STUB_ENTRY(87)
STUB_ENTRY(88)
STUB_ENTRY(89)
STUB_ENTRY(90)
STUB_ENTRY(91)
STUB_ENTRY(92)
STUB_ENTRY(93)
STUB_ENTRY(94)
STUB_ENTRY(95)
STUB_ENTRY(96)
STUB_ENTRY(97)
STUB_ENTRY(98)
STUB_ENTRY(99)
STUB_ENTRY(100)
STUB_ENTRY(101)
STUB_ENTRY(102)
STUB_ENTRY(103)
STUB_ENTRY(104)
STUB_ENTRY(105)
STUB_ENTRY(106)
STUB_ENTRY(107)
STUB_ENTRY(108)
STUB_ENTRY(109)
STUB_ENTRY(110)
STUB_ENTRY(111)
STUB_ENTRY(112)
STUB_ENTRY(113)
STUB_ENTRY(114)
STUB_ENTRY(115)
STUB_ENTRY(116)
STUB_ENTRY(117)
STUB_ENTRY(118)
STUB_ENTRY(119)
STUB_ENTRY(120)
STUB_ENTRY(121)
STUB_ENTRY(122)
STUB_ENTRY(123)
STUB_ENTRY(124)
STUB_ENTRY(125)
STUB_ENTRY(126)
STUB_ENTRY(127)
STUB_ENTRY(128)
STUB_ENTRY(129)
STUB_ENTRY(130)
STUB_ENTRY(131)
STUB_ENTRY(132)
STUB_ENTRY(133)
STUB_ENTRY(134)
STUB_ENTRY(135)
STUB_ENTRY(136)
STUB_ENTRY(137)
STUB_ENTRY(138)
STUB_ENTRY(139)
STUB_ENTRY(140)
STUB_ENTRY(141)
STUB_ENTRY(142)
STUB_ENTRY(143)
STUB_ENTRY(144)
STUB_ENTRY(145)
STUB_ENTRY(146)
STUB_ENTRY(147)
STUB_ENTRY(148)
STUB_ENTRY(149)
STUB_ENTRY(150)
STUB_ENTRY(151)
STUB_ENTRY(152)
STUB_ENTRY(153)
STUB_ENTRY(154)
STUB_ENTRY(155)
STUB_ENTRY(156)
STUB_ENTRY(157)
STUB_ENTRY(158)
STUB_ENTRY(159)
STUB_ENTRY(160)
STUB_ENTRY(161)
STUB_ENTRY(162)
STUB_ENTRY(163)
STUB_ENTRY(164)
STUB_ENTRY(165)
STUB_ENTRY(166)
STUB_ENTRY(167)
STUB_ENTRY(168)
STUB_ENTRY(169)
STUB_ENTRY(170)
STUB_ENTRY(171)
STUB_ENTRY(172)
STUB_ENTRY(173)
STUB_ENTRY(174)
STUB_ENTRY(175)
STUB_ENTRY(176)
STUB_ENTRY(177)
STUB_ENTRY(178)
STUB_ENTRY(179)
STUB_ENTRY(180)
STUB_ENTRY(181)
STUB_ENTRY(182)
STUB_ENTRY(183)
STUB_ENTRY(184)
STUB_ENTRY(185)
STUB_ENTRY(186)
STUB_ENTRY(187)
STUB_ENTRY(188)
STUB_ENTRY(189)
STUB_ENTRY(190)
STUB_ENTRY(191)
STUB_ENTRY(192)
STUB_ENTRY(193)
STUB_ENTRY(194)
STUB_ENTRY(195)
STUB_ENTRY(196)
STUB_ENTRY(197)
STUB_ENTRY(198)
STUB_ENTRY(199)
STUB_ENTRY(200)
STUB_ENTRY(201)
STUB_ENTRY(202)
STUB_ENTRY(203)
STUB_ENTRY(204)
STUB_ENTRY(205)
STUB_ENTRY(206)
STUB_ENTRY(207)
STUB_ENTRY(208)
STUB_ENTRY(209)
STUB_ENTRY(210)
STUB_ENTRY(211)
STUB_ENTRY(212)
STUB_ENTRY(213)
STUB_ENTRY(214)
STUB_ENTRY(215)
STUB_ENTRY(216)
STUB_ENTRY(217)
STUB_ENTRY(218)
STUB_ENTRY(219)
STUB_ENTRY(220)
STUB_ENTRY(221)
STUB_ENTRY(222)
STUB_ENTRY(223)
STUB_ENTRY(224)
STUB_ENTRY(225)
STUB_ENTRY(226)
STUB_ENTRY(227)
STUB_ENTRY(228)
STUB_ENTRY(229)
STUB_ENTRY(230)
STUB_ENTRY(231)
STUB_ENTRY(232)
STUB_ENTRY(233)
STUB_ENTRY(234)
STUB_ENTRY(235)
STUB_ENTRY(236)
STUB_ENTRY(237)
STUB_ENTRY(238)
STUB_ENTRY(239)
STUB_ENTRY(240)
STUB_ENTRY(241)
STUB_ENTRY(242)
STUB_ENTRY(243)
STUB_ENTRY(244)
STUB_ENTRY(245)
STUB_ENTRY(246)
STUB_ENTRY(247)
STUB_ENTRY(248)
STUB_ENTRY(249)
STUB_ENTRY(250)
STUB_ENTRY(251)
STUB_ENTRY(252)
STUB_ENTRY(253)
STUB_ENTRY(254)
STUB_ENTRY(255)
STUB_ENTRY(256)
STUB_ENTRY(257)
STUB_ENTRY(258)
SENTINEL_ENTRY(0)
SENTINEL_ENTRY(1)
SENTINEL_ENTRY(2)
SENTINEL_ENTRY(3)
SENTINEL_ENTRY(4)
SENTINEL_ENTRY(5)
SENTINEL_ENTRY(6)
SENTINEL_ENTRY(7)
SENTINEL_ENTRY(8)
SENTINEL_ENTRY(9)

View File

@ -0,0 +1,204 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* Class that wraps JS objects to appear as XPCOM objects. */
#include "xpcprivate.h"
// NOTE: much of the fancy footwork is done in xpcstubs.cpp
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
nsresult
nsXPCWrappedJS::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
return mClass->DelegatedQueryInterface(this, aIID, aInstancePtr);
}
// do chained ref counting
nsrefcnt
nsXPCWrappedJS::AddRef(void)
{
NS_PRECONDITION(mRoot, "bad root");
++mRefCnt;
if(1 == mRefCnt && mRoot && mRoot != this)
NS_ADDREF(mRoot);
return mRefCnt;
}
nsrefcnt
nsXPCWrappedJS::Release(void)
{
NS_PRECONDITION(mRoot, "bad root");
NS_PRECONDITION(0 != mRefCnt, "dup release");
--mRefCnt;
if(0 == mRefCnt)
{
if(mRoot == this)
{
NS_DELETEXPCOM(this); // cascaded delete
}
else
{
NS_RELEASE(mRoot);
}
return 0;
}
return mRefCnt;
}
// static
nsXPCWrappedJS*
nsXPCWrappedJS::GetNewOrUsedWrapper(XPCContext* xpcc,
JSObject* aJSObj,
REFNSIID aIID)
{
JSObject2WrappedJSMap* map;
JSObject* rootJSObj;
nsXPCWrappedJS* root;
nsXPCWrappedJS* wrapper = NULL;
nsXPCWrappedJSClass* clazz = NULL;
NS_PRECONDITION(xpcc, "bad param");
NS_PRECONDITION(aJSObj, "bad param");
map = xpcc->GetWrappedJSMap();
if(!map)
{
NS_ASSERTION(map,"bad map");
return NULL;
}
clazz = nsXPCWrappedJSClass::GetNewOrUsedClass(xpcc, aIID);
if(!clazz)
return NULL;
// from here on we need to return through 'return_wrapper'
// always find the root JSObject
rootJSObj = clazz->GetRootJSObject(aJSObj);
if(!rootJSObj)
goto return_wrapper;
// look for the root wrapper
root = map->Find(rootJSObj);
if(root)
{
wrapper = root->Find(aIID);
if(wrapper)
{
NS_ADDREF(wrapper);
goto return_wrapper;
}
}
else
{
// build the root wrapper
if(rootJSObj == aJSObj)
{
// the root will do double duty as the interface wrapper
wrapper = root = new nsXPCWrappedJS(aJSObj, clazz, NULL);
if(root)
map->Add(root);
goto return_wrapper;
}
else
{
// just a root wrapper
nsXPCWrappedJSClass* rootClazz;
rootClazz = nsXPCWrappedJSClass::GetNewOrUsedClass(xpcc, kISupportsIID);
if(!rootClazz)
goto return_wrapper;
root = new nsXPCWrappedJS(rootJSObj, rootClazz, NULL);
NS_RELEASE(rootClazz);
if(!root)
goto return_wrapper;
map->Add(root);
}
}
// at this point we have a root and may need to build the specific wrapper
NS_ASSERTION(root,"bad root");
NS_ASSERTION(clazz,"bad clazz");
if(!wrapper)
{
wrapper = new nsXPCWrappedJS(aJSObj, clazz, root);
if(!wrapper)
goto return_wrapper;
}
wrapper->mNext = root->mNext;
root->mNext = wrapper;
return_wrapper:
if(clazz)
NS_RELEASE(clazz);
return wrapper;
}
#ifdef WIN32
#pragma warning(disable : 4355) // OK to pass "this" in member initializer
#endif
nsXPCWrappedJS::nsXPCWrappedJS(JSObject* aJSObj,
nsXPCWrappedJSClass* aClass,
nsXPCWrappedJS* root)
: mJSObj(aJSObj),
mClass(aClass),
mRoot(root ? root : this),
mNext(NULL)
{
NS_INIT_REFCNT();
NS_ADDREF_THIS();
NS_ADDREF(aClass);
JS_AddRoot(mClass->GetXPCContext()->GetJSContext(), &mJSObj);
}
nsXPCWrappedJS::~nsXPCWrappedJS()
{
NS_PRECONDITION(0 == mRefCnt, "refcounting error");
JS_RemoveRoot(mClass->GetXPCContext()->GetJSContext(), &mJSObj);
NS_RELEASE(mClass);
if(mNext)
NS_DELETEXPCOM(mNext); // cascaded delete
}
nsXPCWrappedJS*
nsXPCWrappedJS::Find(REFNSIID aIID)
{
if(aIID.Equals(kISupportsIID))
return mRoot;
nsXPCWrappedJS* cur = mRoot;
do
{
if(aIID.Equals(GetIID()))
return cur;
} while(NULL != (cur = cur->mNext));
return NULL;
}

View File

@ -0,0 +1,551 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* Platform specific code to invoke XPCOM methods on native objects */
#include "xpcprivate.h"
static const char* XPC_QUERY_INTERFACE_STR = "QueryInterface";
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
NS_IMPL_ISUPPORTS(nsXPCWrappedJSClass, NS_IXPCONNECT_WRAPPED_JS_CLASS_IID)
// static
nsXPCWrappedJSClass*
nsXPCWrappedJSClass::GetNewOrUsedClass(XPCContext* xpcc,
REFNSIID aIID)
{
IID2WrappedJSClassMap* map;
nsXPCWrappedJSClass* clazz = NULL;
NS_PRECONDITION(xpcc, "bad param");
map = xpcc->GetWrappedJSClassMap();
NS_ASSERTION(map,"bad map");
clazz = map->Find(aIID);
if(clazz)
{
NS_ADDREF(clazz);
}
else
{
nsIInterfaceInfo* info;
nsXPConnect* xpc;
if((xpc = nsXPConnect::GetXPConnect()) != NULL &&
NS_SUCCEEDED(xpc->GetInterfaceInfo(aIID, &info)))
{
clazz = new nsXPCWrappedJSClass(xpcc, aIID, info);
}
}
return clazz;
}
nsXPCWrappedJSClass::nsXPCWrappedJSClass(XPCContext* xpcc, REFNSIID aIID,
nsIInterfaceInfo* aInfo)
: mXPCContext(xpcc),
mIID(aIID),
mInfo(aInfo)
{
NS_ADDREF(mInfo);
NS_INIT_REFCNT();
NS_ADDREF_THIS();
mXPCContext->GetWrappedJSClassMap()->Add(this);
}
nsXPCWrappedJSClass::~nsXPCWrappedJSClass()
{
mXPCContext->GetWrappedJSClassMap()->Remove(this);
NS_RELEASE(mInfo);
}
/***************************************************************************/
// XXX for now IIDs are represented in JS as string objects containing strings
// of the form: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} (just like the nsID
// Parse and ToString methods use.
// XXX lots of room for optimization here!
// JSObject*
// nsXPCWrappedJSClass::CreateIIDJSObject(REFNSIID aIID)
// {
// JSObject* obj = NULL;
// char* str = aIID.ToString();
// if(str)
// {
// JSContext* cx = GetJSContext();
// JSString* jsstr = JS_InternString(cx, str);
// delete [] str;
// if(jsstr)
// JS_ValueToObject(cx, STRING_TO_JSVAL(jsstr), &obj);
// }
// return obj;
// }
JSObject*
nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSObject* jsobj, REFNSIID aIID)
{
JSContext* cx = GetJSContext();
JSObject* id;
jsval retval;
JSObject* retObj;
JSBool success = JS_FALSE;
// id = CreateIIDJSObject(aIID);
id = xpc_NewIDObject(cx, aIID);
if(id)
{
JSErrorReporter older = JS_SetErrorReporter(cx, NULL);
jsval args[1] = {OBJECT_TO_JSVAL(id)};
success = JS_CallFunctionName(cx, jsobj, XPC_QUERY_INTERFACE_STR,
1, args, &retval);
if(success)
success = JS_ValueToObject(cx, retval, &retObj);
JS_SetErrorReporter(cx, older);
}
return success ? retObj : NULL;
}
/***************************************************************************/
// This 'WrappedJSIdentity' class and singleton allow us to figure out if
// any given nsISupports* is implemented by a WrappedJS object. This is done
// using a QueryInterface call on the interface pointer with our ID. If
// that call returns NS_OK and the pointer is to our singleton, then the
// interface must be implemented by a WrappedJS object. NOTE: the
// 'WrappedJSIdentity' object is not a real XPCOM object and should not be
// used for anything else (hence it is declared in this implementation file).
// {5C5C3BB0-A9BA-11d2-BA64-00805F8A5DD7}
#define NS_IXPCONNECT_WRAPPED_JS_IDENTITY_CLASS_IID \
{ 0x5c5c3bb0, 0xa9ba, 0x11d2, \
{ 0xba, 0x64, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
static NS_DEFINE_IID(kIWrappedJSIdentityIID, NS_IXPCONNECT_WRAPPED_JS_IDENTITY_CLASS_IID);
class WrappedJSIdentity
{
// no instance methods...
public:
static void* GetSingleton()
{
static WrappedJSIdentity* singleton = NULL;
if(!singleton)
singleton = new WrappedJSIdentity();
return (void*) singleton;
}
};
/***************************************************************************/
JSBool
nsXPCWrappedJSClass::IsWrappedJS(nsISupports* aPtr)
{
void* result;
NS_PRECONDITION(aPtr, "null pointer");
return aPtr &&
NS_OK == aPtr->QueryInterface(kIWrappedJSIdentityIID, &result) &&
result == WrappedJSIdentity::GetSingleton();
}
nsresult
nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
REFNSIID aIID,
void** aInstancePtr)
{
if(NULL == aInstancePtr)
{
NS_PRECONDITION(0, "null pointer");
return NS_ERROR_NULL_POINTER;
}
if(aIID.Equals(kISupportsIID))
{
nsXPCWrappedJS* root = self->GetRootWrapper();
*aInstancePtr = (void*) root;
NS_ADDREF(root);
return NS_OK;
}
else if(aIID.Equals(self->GetIID()))
{
*aInstancePtr = (void*) self;
NS_ADDREF(self);
return NS_OK;
}
else if(aIID.Equals(kIWrappedJSIdentityIID))
{
*aInstancePtr = WrappedJSIdentity::GetSingleton();
return NS_OK;
}
else
{
JSObject* jsobj =
CallQueryInterfaceOnJSObject(self->GetJSObject(), aIID);
if(jsobj)
{
nsXPCWrappedJS* wrapper =
nsXPCWrappedJS::GetNewOrUsedWrapper(GetXPCContext(),
jsobj, aIID);
if(wrapper)
{
*aInstancePtr = (void*) wrapper;
return NS_OK;
}
}
}
*aInstancePtr = NULL;
return NS_NOINTERFACE;
}
JSObject*
nsXPCWrappedJSClass::GetRootJSObject(JSObject* aJSObj)
{
JSObject* result = CallQueryInterfaceOnJSObject(aJSObj, kISupportsIID);
return result ? result : aJSObj;
}
#define JAM_DOUBLE(v,d) (d = (jsdouble)v, DOUBLE_TO_JSVAL(&d))
#define FIT_32(i,d) (INT_FITS_IN_JSVAL(i) ? INT_TO_JSVAL(i) : JAM_DOUBLE(i,d))
// Win32 can't handle uint64 to double conversion
#define JAM_DOUBLE_U64(v,d) JAM_DOUBLE(((int64)v),d)
nsresult
nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper,
const nsXPCMethodInfo* info,
nsXPCMiniVarient* params)
{
#define ARGS_BUFFER_COUNT 32
jsval argsBuffer[ARGS_BUFFER_COUNT];
jsval* argv = NULL;
uint8 i;
uint8 argc;
jsval result;
uint8 paramCount;
nsresult retval = NS_ERROR_UNEXPECTED;
JSErrorReporter older;
JSBool success;
JSContext* cx = GetJSContext();
// XXX ASSUMES that retval is last arg.
paramCount = info->GetParamCount();
argc = paramCount -
(paramCount && info->GetParam(paramCount-1).IsRetval() ? 1 : 0);
// XXX do we need to go through and NULL out all 'out' params?
// setup argv
if(argc > ARGS_BUFFER_COUNT)
{
if(!(argv = new jsval[argc]))
return NS_ERROR_OUT_OF_MEMORY;
}
else
argv = argsBuffer;
// from here on out we exit via 'goto done'
// build the args
for(i = 0; i < argc; i++)
{
const nsXPCParamInfo& param = info->GetParam(i);
const nsXPCType& type = param.GetType();
jsval val;
if(param.IsIn())
{
nsXPCMiniVarient* pv;
if(param.IsOut())
pv = (nsXPCMiniVarient*) params[i].val.p;
else
pv = &params[i];
if(type & nsXPCType::IS_POINTER)
pv = (nsXPCMiniVarient*) pv->val.p;
// do the actual conversion...
// handle special cases first
if(type == nsXPCType::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");
continue;
}
else if(type == nsXPCType::T_INTERFACE_IS)
{
// XXX implement INTERFACE_IS
NS_ASSERTION(0,"interface_is params not supported");
continue;
}
else if(type == nsXPCType::T_STRING)
{
// XXX implement STRING
NS_ASSERTION(0,"string params not supported");
continue;
}
else if(type == nsXPCType::T_P_IID)
{
// XXX implement IID
NS_ASSERTION(0,"iid params not supported");
continue;
}
else if(type == nsXPCType::T_P_VOID)
{
// XXX implement void*
NS_ASSERTION(0,"void* params not supported");
continue;
}
else {
jsdouble d;
switch(type & nsXPCType::TYPE_MASK)
{
case nsXPCType::T_I8 : val = INT_TO_JSVAL((int32)pv->val.i8); break;
case nsXPCType::T_I16 : val = INT_TO_JSVAL((int32)pv->val.i16); break;
case nsXPCType::T_I32 : val = FIT_32(pv->val.i32,d); break;
case nsXPCType::T_I64 : val = JAM_DOUBLE(pv->val.i64,d); break;
case nsXPCType::T_U8 : val = INT_TO_JSVAL((int32)pv->val.u8); break;
case nsXPCType::T_U16 : val = INT_TO_JSVAL((int32)pv->val.u16); break;
case nsXPCType::T_U32 : val = FIT_32(pv->val.u32,d); break;
case nsXPCType::T_U64 : val = JAM_DOUBLE_U64(pv->val.u64,d); break;
case nsXPCType::T_FLOAT : val = JAM_DOUBLE(pv->val.f,d); break;
case nsXPCType::T_DOUBLE : val = DOUBLE_TO_JSVAL(&pv->val.d); break;
case nsXPCType::T_BOOL : val = pv->val.b?JSVAL_TRUE:JSVAL_FALSE; break;
// XXX need to special case cahr* and wchar_t*
case nsXPCType::T_CHAR : val = INT_TO_JSVAL((int32)pv->val.c); break;
case nsXPCType::T_WCHAR : val = INT_TO_JSVAL((int32)pv->val.wc); break;
default:
NS_ASSERTION(0, "bad type");
continue;
}
}
}
if(param.IsOut())
{
// create an 'out' object
JSObject* obj = NewOutObject();
if(param.IsIn())
{
if(!JS_SetProperty(cx, obj, XPC_VAL_STR, &val))
goto done;
}
argv[i] = OBJECT_TO_JSVAL(obj);
}
else
argv[i] = val;
}
// do the function call
older = JS_SetErrorReporter(cx, NULL);
success = JS_CallFunctionName(cx, wrapper->GetJSObject(), info->GetName(),
argc, argv, &result);
JS_SetErrorReporter(cx, older);
if(!success)
{
retval = NS_ERROR_FAILURE;
goto done;
}
// convert out args and result
// NOTE: this is the total number of native params, not just the args
for(i = 0; i < paramCount; i++)
{
const nsXPCParamInfo& param = info->GetParam(i);
if(param.IsOut())
{
jsval val;
const nsXPCType& type = param.GetType();
nsXPCMiniVarient* pv;
if(param.IsRetval())
val = result;
else if(!JS_GetProperty(cx, JSVAL_TO_OBJECT(argv[i]), XPC_VAL_STR, &val))
goto done;
pv = (nsXPCMiniVarient*) params[i].val.p;
if(type & nsXPCType::IS_POINTER)
pv = (nsXPCMiniVarient*) pv->val.p;
// do the actual conversion...
// handle special cases first
if(type == nsXPCType::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");
continue;
}
else if(type == nsXPCType::T_INTERFACE_IS)
{
// XXX implement INTERFACE_IS
NS_ASSERTION(0,"interface_is params not supported");
continue;
}
else if(type == nsXPCType::T_STRING)
{
// XXX implement STRING
NS_ASSERTION(0,"string params not supported");
continue;
}
else if(type == nsXPCType::T_P_IID)
{
// XXX implement IID
NS_ASSERTION(0,"iid params not supported");
continue;
}
else if(type == nsXPCType::T_P_VOID)
{
// XXX implement void*
NS_ASSERTION(0,"void* params not supported");
continue;
}
else {
int32 ti;
uint32 tu;
jsdouble td;
JSBool r;
switch(type & nsXPCType::TYPE_MASK)
{
case nsXPCType::T_I8 :
r = JS_ValueToECMAInt32(cx,val,&ti);
pv->val.i8 = (int8) ti;
break;
case nsXPCType::T_I16 :
r = JS_ValueToECMAInt32(cx,val,&ti);
pv->val.i16 = (int16) ti;
break;
case nsXPCType::T_I32 :
r = JS_ValueToECMAInt32(cx,val,&pv->val.i32);
break;
case nsXPCType::T_I64 :
if(JSVAL_IS_INT(val))
{
r = JS_ValueToECMAInt32(cx,val,&ti);
pv->val.i64 = (int64) ti;
}
else
{
r = JS_ValueToNumber(cx, val, &td);
if(r) pv->val.i64 = (int64) td;
}
break;
case nsXPCType::T_U8 :
r = JS_ValueToECMAUint32(cx,val,&tu);
pv->val.u8 = (uint8) tu;
break;
case nsXPCType::T_U16 :
r = JS_ValueToECMAUint32(cx,val,&tu);
pv->val.u16 = (uint16) tu;
break;
case nsXPCType::T_U32 :
r = JS_ValueToECMAUint32(cx,val,&pv->val.u32);
break;
case nsXPCType::T_U64 :
if(JSVAL_IS_INT(val))
{
r = JS_ValueToECMAUint32(cx,val,&tu);
pv->val.i64 = (int64) tu;
}
else
{
r = JS_ValueToNumber(cx, val, &td);
// XXX Win32 can't handle double to uint64 directly
if(r) pv->val.u64 = (uint64)((int64) td);
}
break;
case nsXPCType::T_FLOAT :
r = JS_ValueToNumber(cx, val, &td);
if(r) pv->val.f = (float) td;
break;
case nsXPCType::T_DOUBLE :
r = JS_ValueToNumber(cx, val, &pv->val.d);
break;
case nsXPCType::T_BOOL :
r = JS_ValueToBoolean(cx, val, &pv->val.b);
break;
// XXX should we special case char* and wchar_t* to be strings?
case nsXPCType::T_CHAR :
case nsXPCType::T_WCHAR :
default:
NS_ASSERTION(0, "bad type");
goto done;
}
continue;
}
}
}
retval = NS_OK;
done:
if(argv && argv != argsBuffer)
delete [] argv;
return retval;
}
static JSClass WrappedJSOutArg_class = {
"XPCOutArg", 0,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
};
// static
JSBool
nsXPCWrappedJSClass::InitForContext(XPCContext* xpcc)
{
if (!JS_InitClass(xpcc->GetJSContext(), xpcc->GetGlobalObject(),
0, &WrappedJSOutArg_class, 0, 0,
0, 0,
0, 0))
return JS_FALSE;
return JS_TRUE;
}
JSObject*
nsXPCWrappedJSClass::NewOutObject()
{
return JS_NewObject(GetJSContext(), &WrappedJSOutArg_class, NULL, NULL);
}

View File

@ -112,7 +112,7 @@ nsXPCWrappedNative::GetNewOrUsedWrapper(XPCContext* xpcc,
if(!clazz)
goto return_wrapper;
// build the root wrapper
// build the root wrapper
if(!root)
{
@ -153,18 +153,20 @@ nsXPCWrappedNative::GetNewOrUsedWrapper(XPCContext* xpcc,
}
}
// at this point we have a root and need to build the specific wrapper
// at this point we have a root and may need to build the specific wrapper
NS_ASSERTION(root,"bad root");
NS_ASSERTION(clazz,"bad clazz");
wrapper = new nsXPCWrappedNative(aObj, clazz, root);
if(!wrapper)
goto return_wrapper;
if(!wrapper->mJSObj)
{
NS_RELEASE(wrapper);
goto return_wrapper;
wrapper = new nsXPCWrappedNative(aObj, clazz, root);
if(!wrapper)
goto return_wrapper;
if(!wrapper->mJSObj)
{
NS_RELEASE(wrapper); // sets wrapper to NULL
goto return_wrapper;
}
}
wrapper->mNext = root->mNext;
@ -215,7 +217,6 @@ nsXPCWrappedNative::~nsXPCWrappedNative()
NS_DELETEXPCOM(mNext); // cascaded delete
}
nsXPCWrappedNative*
nsXPCWrappedNative::Find(REFNSIID aIID)
{
@ -225,7 +226,7 @@ nsXPCWrappedNative::Find(REFNSIID aIID)
nsXPCWrappedNative* cur = mRoot;
do
{
if(aIID.Equals(cur->GetClass()->GetIID()))
if(aIID.Equals(GetIID()))
return cur;
} while(NULL != (cur = cur->mNext));

View File

@ -12,7 +12,7 @@
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
@ -20,7 +20,7 @@
#include "xpcprivate.h"
static const char* XPC_VAL_STR = "val";
const char* XPC_VAL_STR = "val";
NS_IMPL_ISUPPORTS(nsXPCWrappedNativeClass, NS_IXPCONNECT_WRAPPED_NATIVE_CLASS_IID)
@ -30,7 +30,7 @@ nsXPCWrappedNativeClass::GetNewOrUsedClass(XPCContext* xpcc,
REFNSIID aIID)
{
IID2WrappedNativeClassMap* map;
nsXPCWrappedNativeClass* clazz;
nsXPCWrappedNativeClass* clazz = NULL;
NS_PRECONDITION(xpcc, "bad param");
@ -215,8 +215,9 @@ WrappedNative_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
case JSTYPE_VOID:
case JSTYPE_STRING:
// XXX get the interface name from the InterfaceInfo
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, "WrappedNative"));
// XXX perhaps more expressive toString?
*vp = STRING_TO_JSVAL(
JS_NewStringCopyZ(cx, wrapper->GetClass()->GetInterfaceName()));
return JS_TRUE;
case JSTYPE_NUMBER:
@ -298,51 +299,10 @@ nsXPCWrappedNativeClass::GetInterfaceName() const
return name;
}
void
nsXPCWrappedNativeClass::SetDescriptorCounts(XPCNativeMemberDescriptor* desc)
{
// XXX this is subject to serious improvement!
switch(desc->category)
{
case XPCNativeMemberDescriptor::CONSTANT:
NS_ASSERTION(0,"bad call");
break;
case XPCNativeMemberDescriptor::METHOD:
{
const nsXPCMethodInfo* info;
if(NS_FAILED(mInfo->GetMethodInfo(desc->index, &info)))
break;
uintN scratchWords = 0;
for(int i = info->GetParamCount()-1 ; i >= 0; i--)
{
const nsXPCParamInfo& param = info->GetParam(i);
if(param.IsOut())
{
// XXX what about space for IIDs?
scratchWords += param.GetType().WordCount();
}
}
desc->maxParamCount = info->GetParamCount();
desc->maxScratchWordCount = scratchWords;
break;
}
case XPCNativeMemberDescriptor::ATTRIB_RO:
case XPCNativeMemberDescriptor::ATTRIB_RW:
// just set these for the max possible...
desc->maxParamCount = 1;
desc->maxScratchWordCount = 2;
break;
default:
NS_ASSERTION(0,"bad category");
break;
}
}
// Win32 can't handle u64 to double conversion
#define JAM_DOUBLE_U64(v,d) (d = (jsdouble)(int64)v, DOUBLE_TO_JSVAL(&d))
#define JAM_DOUBLE(v,d) (d = (jsdouble)v, DOUBLE_TO_JSVAL(&d))
#define FIT_32(i,d) (INT_FITS_IN_JSVAL(i) ? INT_TO_JSVAL(i) : JAM_DOUBLE(i,d))
// Win32 can't handle uint64 to double conversion
#define JAM_DOUBLE_U64(v,d) JAM_DOUBLE(((int64)v),d)
JSBool
nsXPCWrappedNativeClass::GetConstantAsJSVal(nsXPCWrappedNative* wrapper,
@ -377,6 +337,7 @@ nsXPCWrappedNativeClass::GetConstantAsJSVal(nsXPCWrappedNative* wrapper,
case nsXPCType::T_CHAR : *vp = INT_TO_JSVAL((int32)var.val.c); break;
case nsXPCType::T_WCHAR : *vp = INT_TO_JSVAL((int32)var.val.wc); break;
default:
// XXX need to support string constants
NS_ASSERTION(0, "bad type");
ReportError(desc, "invalid constant type");
}
@ -398,43 +359,23 @@ nsXPCWrappedNativeClass::CallWrappedMethod(nsXPCWrappedNative* wrapper,
JSBool isAttributeSet,
uintN argc, jsval *argv, jsval *vp)
{
#define PARAM_COUNT 32
#define SCRATCH_WORDS 32
#define PARAM_BUFFER_COUNT 32
nsXPCVarient paramBuffer[PARAM_COUNT];
uint32 scratchBuffer[SCRATCH_WORDS];
nsXPCVarient paramBuffer[PARAM_BUFFER_COUNT];
JSBool retval = JS_FALSE;
nsXPCVarient* dispatchParams = NULL;
uint32* scratch = NULL;
uint32 scratchIndex = 0;
JSContext* cx = GetJSContext();
uint8 i;
const nsXPCMethodInfo* info;
uint8 requiredArgs;
uint8 paramCount;
uint8 dispatchParamsInitedCount = 0;
jsval src;
jsdouble num;
uint8 vtblIndex;
nsresult invokeResult;
// setup buffers
if(GetMaxParamCount(desc) > PARAM_COUNT)
dispatchParams = new nsXPCVarient[GetMaxParamCount(desc)];
else
dispatchParams = paramBuffer;
if(GetMaxScratchWordCount(desc) > SCRATCH_WORDS)
scratch = new uint32[GetMaxScratchWordCount(desc)];
else
scratch = scratchBuffer;
if(!dispatchParams || !scratch)
{
ReportError(desc, "out of memeory");
goto done;
}
*vp = JSVAL_NULL;
// make sure we have what we need
if(isAttributeSet)
@ -463,94 +404,312 @@ nsXPCWrappedNativeClass::CallWrappedMethod(nsXPCWrappedNative* wrapper,
goto done;
}
// setup varient array pointer
if(paramCount > PARAM_BUFFER_COUNT)
{
if(!(dispatchParams = new nsXPCVarient[paramCount]))
{
ReportError(desc, "out of memory");
goto done;
}
}
else
dispatchParams = paramBuffer;
// iterate through the params doing conversions
for(i = 0; i < paramCount; i++)
{
const nsXPCParamInfo& param = info->GetParam(i);
const nsXPCType& type = param.GetType();
nsXPCVarient* dp;
nsXPCVarient* dp = &dispatchParams[i];
dp->type = type;
dp->flags = 0;
dp->val.p = NULL;
dispatchParamsInitedCount++;
dispatchParams[i].type = type;
// set 'src' to be the object from which we get the value and
// prepare for out param
if(param.IsOut())
{
dispatchParams[i].val.p = &scratch[scratchIndex];
scratchIndex += type.WordCount();
if(!param.IsIn())
continue;
dp = (nsXPCVarient*)dispatchParams[i].val.p;
}
else
dp = &dispatchParams[i];
dp->flags = nsXPCVarient::PTR_IS_DATA;
// XXX fix this mess...
if(type & ~nsXPCType::TYPE_MASK)
{
NS_ASSERTION(0,"not supported");
continue;
}
// set 'src' to be the object from which we get the value
if(param.IsOut() /* implicit && param.IsIn() */ )
{
if(!JSVAL_IS_OBJECT(argv[i]) ||
!JS_GetProperty(cx, JSVAL_TO_OBJECT(argv[i]), XPC_VAL_STR, &src))
// XXX are there no type alignment issues here?
if(type & nsXPCType::IS_POINTER)
{
ReportError(desc, "no out val");
dp->ptr = &dp->ptr2;
dp->ptr2 = &dp->val;
}
else
dp->ptr = &dp->val;
if(!param.IsRetval() &&
(!JSVAL_IS_OBJECT(argv[i]) ||
!JS_GetProperty(cx, JSVAL_TO_OBJECT(argv[i]), XPC_VAL_STR, &src)))
{
ReportError(desc, "out argument must be object");
goto done;
}
if(!param.IsIn())
{
// We don't need to convert the jsval.
// XXX for an out param *I think* I might need to set the flags
// to VAL_IS_OWNED (after clearing val.p) if the type is
// 'IS_POINTER' because I think the caller may have to take
// over ownership of a pointer. But, this depends on the
// type of the thing.
continue;
}
}
else
src = argv[i];
// XXX just ASSUME a number
if(!JS_ValueToNumber(cx, src, &num))
{
ReportError(desc, "could not convert argument to a number");
goto done;
if(type & nsXPCType::IS_POINTER)
{
dp->ptr = &dp->val;
dp->flags = nsXPCVarient::PTR_IS_DATA;
}
src = argv[i];
}
switch(type)
// do the actual conversion...
// handle special cases first
if(type == nsXPCType::T_INTERFACE)
{
case nsXPCType::T_I8 : dp->val.i8 = (int8) num; break;
case nsXPCType::T_I16 : dp->val.i16 = (int16) num; break;
case nsXPCType::T_I32 : dp->val.i32 = (int32) num; break;
case nsXPCType::T_I64 : dp->val.i64 = (int64) num; break;
case nsXPCType::T_U8 : dp->val.u8 = (uint8) num; break;
case nsXPCType::T_U16 : dp->val.u16 = (uint16) num; break;
case nsXPCType::T_U32 : dp->val.u32 = (uint32) num; break;
case nsXPCType::T_U64 : dp->val.u64 = (uint64) num; break;
case nsXPCType::T_FLOAT : dp->val.f = (float) num; break;
case nsXPCType::T_DOUBLE : dp->val.d = (double) num; break;
case nsXPCType::T_BOOL : dp->val.b = (PRBool) num; break;
case nsXPCType::T_CHAR : dp->val.c = (char) num; break;
case nsXPCType::T_WCHAR : dp->val.wc = (wchar_t) num; break;
default:
NS_ASSERTION(0, "bad type");
ReportError(desc, "could not convert argument to a number");
goto done;
// 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");
continue;
}
else if(type == nsXPCType::T_INTERFACE_IS)
{
// XXX implement INTERFACE_IS
NS_ASSERTION(0,"interface_is params not supported");
continue;
}
else if(type == nsXPCType::T_STRING)
{
// XXX implement STRING
NS_ASSERTION(0,"string params not supported");
continue;
}
else if(type == nsXPCType::T_P_IID)
{
// XXX implement IID
NS_ASSERTION(0,"iid params not supported");
continue;
}
else if(type == nsXPCType::T_P_VOID)
{
// XXX implement void*
NS_ASSERTION(0,"void* params not supported");
continue;
}
else {
int32 ti;
uint32 tu;
jsdouble td;
JSBool r;
switch(type & nsXPCType::TYPE_MASK)
{
case nsXPCType::T_I8 :
r = JS_ValueToECMAInt32(cx,src,&ti);
dp->val.i8 = (int8) ti;
break;
case nsXPCType::T_I16 :
r = JS_ValueToECMAInt32(cx,src,&ti);
dp->val.i16 = (int16) ti;
break;
case nsXPCType::T_I32 :
r = JS_ValueToECMAInt32(cx,src,&dp->val.i32);
break;
case nsXPCType::T_I64 :
if(JSVAL_IS_INT(src))
{
r = JS_ValueToECMAInt32(cx,src,&ti);
dp->val.i64 = (int64) ti;
}
else
{
r = JS_ValueToNumber(cx, src, &td);
if(r) dp->val.i64 = (int64) td;
}
break;
case nsXPCType::T_U8 :
r = JS_ValueToECMAUint32(cx,src,&tu);
dp->val.u8 = (uint8) tu;
break;
case nsXPCType::T_U16 :
r = JS_ValueToECMAUint32(cx,src,&tu);
dp->val.u16 = (uint16) tu;
break;
case nsXPCType::T_U32 :
r = JS_ValueToECMAUint32(cx,src,&dp->val.u32);
break;
case nsXPCType::T_U64 :
if(JSVAL_IS_INT(src))
{
r = JS_ValueToECMAUint32(cx,src,&tu);
dp->val.i64 = (int64) tu;
}
else
{
r = JS_ValueToNumber(cx, src, &td);
// XXX Win32 can't handle double to uint64 directly
if(r) dp->val.u64 = (uint64)((int64) td);
}
break;
case nsXPCType::T_FLOAT :
r = JS_ValueToNumber(cx, src, &td);
if(r) dp->val.f = (float) td;
break;
case nsXPCType::T_DOUBLE :
r = JS_ValueToNumber(cx, src, &dp->val.d);
break;
case nsXPCType::T_BOOL :
r = JS_ValueToBoolean(cx, src, &dp->val.b);
break;
// XXX should we special case char* and wchar_t* to be strings?
case nsXPCType::T_CHAR :
case nsXPCType::T_WCHAR :
default:
NS_ASSERTION(0, "bad type");
ReportError(desc, "could not convert argument");
goto done;
}
continue;
}
}
// do the invoke
invokeResult = xpc_InvokeNativeMethod(wrapper->GetNative(),vtblIndex,
invokeResult = xpc_InvokeNativeMethod(wrapper->GetNative(), vtblIndex,
paramCount, dispatchParams);
if(NS_FAILED(invokeResult))
{
// XXX this (and others!) should throw rather than report error
ReportError(desc, "XPCOM object returned failure");
goto done;
}
// iterate through the params to gather the results
for(i = 0; i < paramCount; i++)
{
const nsXPCParamInfo& param = info->GetParam(i);
const nsXPCType& type = param.GetType();
// set the retval for success
nsXPCVarient* dp = &dispatchParams[i];
if(param.IsOut())
{
jsval v;
if(type == nsXPCType::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");
goto done;
continue;
}
else if(type == nsXPCType::T_INTERFACE_IS)
{
// XXX implement INTERFACE_IS
NS_ASSERTION(0,"interface_is params not supported");
continue;
}
else if(type == nsXPCType::T_STRING)
{
// XXX implement STRING
NS_ASSERTION(0,"string params not supported");
continue;
}
else if(type == nsXPCType::T_P_IID)
{
// XXX implement IID
NS_ASSERTION(0,"iid params not supported");
continue;
}
else if(type == nsXPCType::T_P_VOID)
{
// XXX implement void*
NS_ASSERTION(0,"void* params not supported");
continue;
}
else
{
jsdouble d;
switch(type & nsXPCType::TYPE_MASK)
{
case nsXPCType::T_I8 :v = INT_TO_JSVAL((int32)dp->val.i8); break;
case nsXPCType::T_I16 :v = INT_TO_JSVAL((int32)dp->val.i16); break;
case nsXPCType::T_I32 :v = FIT_32(dp->val.i32,d); break;
case nsXPCType::T_I64 :v = JAM_DOUBLE(dp->val.i64,d); break;
case nsXPCType::T_U8 :v = INT_TO_JSVAL((int32)dp->val.u8); break;
case nsXPCType::T_U16 :v = INT_TO_JSVAL((int32)dp->val.u16); break;
case nsXPCType::T_U32 :v = FIT_32(dp->val.u32,d); break;
case nsXPCType::T_U64 :v = JAM_DOUBLE_U64(dp->val.u64,d); break;
case nsXPCType::T_FLOAT :v = JAM_DOUBLE(dp->val.f,d); break;
case nsXPCType::T_DOUBLE:v = DOUBLE_TO_JSVAL(&dp->val.d); break;
case nsXPCType::T_BOOL :v = dp->val.b?JSVAL_TRUE:JSVAL_FALSE; break;
// XXX should we special case char* and wchar_t* to be strings?
case nsXPCType::T_CHAR :/*v = INT_TO_JSVAL((int32)dp->val.c); */ break;
case nsXPCType::T_WCHAR :/*v = INT_TO_JSVAL((int32)dp->val.wc);*/ break;
default:
// XXX need to support string constants
NS_ASSERTION(0, "bad type");
ReportError(desc, "invalid out type");
goto done;
}
}
if(param.IsRetval())
*vp = v;
else
{
// we actually assured this before doing the invoke
NS_ASSERTION(JSVAL_IS_OBJECT(argv[i]), "out var is not object");
if(!JS_SetProperty(cx, JSVAL_TO_OBJECT(argv[i]), XPC_VAL_STR, &v))
{
ReportError(desc, "Can't set val on out param object");
goto done;
}
}
}
}
retval = JS_TRUE;
done:
// iterate through the params that were init'd (again!) and clean up
// any alloc'd stuff and release wrappers of params
for(i = 0; i < dispatchParamsInitedCount; i++)
{
nsXPCVarient* dp = &dispatchParams[i];
void* p = dp->val.p;
// XXX verify that ALL this this stuff is right
if(!p)
continue;
if(dp->flags & nsXPCVarient::VAL_IS_OWNED)
delete [] p;
else if(info->GetParam(i).GetType() == nsXPCType::T_INTERFACE)
((nsISupports*)p)->Release();
}
if(dispatchParams && dispatchParams != paramBuffer)
delete [] dispatchParams;
if(scratch && scratch != scratchBuffer)
delete [] scratch;
return retval;
}
@ -848,7 +1007,7 @@ WrappedNative_finalize(JSContext *cx, JSObject *obj)
wrapper->JSObjectFinalized();
}
JSObjectOps WrappedNative_ops = {
static JSObjectOps WrappedNative_ops = {
/* Mandatory non-null function pointer members. */
NULL, /* newObjectMap */
NULL, /* destroyObjectMap */
@ -878,7 +1037,7 @@ WrappedNative_getObjectOps(JSContext *cx, JSClass *clazz)
return &WrappedNative_ops;
}
JSClass WrappedNative_class = {
static JSClass WrappedNative_class = {
"XPCWrappedNative", JSCLASS_HAS_PRIVATE,
NULL, NULL, NULL, NULL,
NULL, NULL, WrappedNative_convert, WrappedNative_finalize,
@ -907,9 +1066,8 @@ nsXPCWrappedNativeClass::InitForContext(XPCContext* xpcc)
JSObject*
nsXPCWrappedNativeClass::NewInstanceJSObject(nsXPCWrappedNative* self)
{
JSContext* cx = GetXPCContext()->GetJSContext();
JSContext* cx = GetJSContext();
JSObject* jsobj = JS_NewObject(cx, &WrappedNative_class, NULL, NULL);
// GetXPCContext()->GetGlobalObject());
if(!jsobj || !JS_SetPrivate(cx, jsobj, self))
return NULL;
return jsobj;