Bug 173146 - Add support to XPConnect for IDispatch interface. Second round of changes. r=adamlock, sr=jst. Most changes are not part of build.

This commit is contained in:
dbradley%netscape.com 2002-11-12 08:22:35 +00:00
Родитель fe881b976d
Коммит 64676a5373
22 изменённых файлов: 1149 добавлений и 287 удалений

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

@ -59,4 +59,10 @@ XPIDLSRCS = \
XPCIDispatch.idl \
$(NULL)
ifdef XPC_IDISPATCH_SUPPORT
XPIDLSRCS += \
nsIDispatchSupport.idl \
$(NULL)
endif
include $(topsrcdir)/config/rules.mk

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

@ -1,4 +1,5 @@
/* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version

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

@ -0,0 +1,78 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the IDispatch implementation for XPConnect
*
* The Initial Developer of the Original Code is
* David Bradley.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsIVariant.idl"
%{ C++
// {40c4883d-079f-43db-82a9-df0a59d37998}
#define NS_IDISPATCH_SUPPORT_CID \
{ 0x40c4883d, 0x079f, 0x43db, \
{ 0x82, 0xa9, 0xdf, 0x0a, 0x59, 0xd3, 0x79, 0x98 } }
#define NS_IDISPATCH_SUPPORT_CONTRACTID "@mozilla.org/nsdispatchsupport;1"
%}
native COMVARIANT(VARIANT);
[ptr] native COMVARIANTPtr(VARIANT);
native JSVal(jsval);
interface IDispatch;
[uuid(38df70e9-12f8-4732-af91-df36c38dc6f6)]
interface nsIDispatchSupport : nsISupports
{
/**
* Converts a COM Variant to a jsval
* @param comvar The COM Variant to be converted
* @param val The jsval to receive the converted value
*/
void COMVariant2JSVal(in COMVARIANTPtr comvar, out JSVal val);
/**
* Converts a jsval to a COM Variant
* @param var The jsval to be converted
* @param comvar The COM Variant to receive the converted value
*/
void JSVal2COMVariant(in JSVal var, out COMVARIANT comvar);
/**
* Instantiate a COM component
* This checks to see if the component is scriptable. If it is, it instantiates it
* @param className contract ID or class ID of the desired component to instantiate
* @return The IDispatch interface pointer if instantiated
*/
IDispatch CreateInstance(in string className, in PRBool testScriptability);
};

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

@ -82,16 +82,20 @@ CPPSRCS = \
xpcwrappednativeinfo.cpp \
xpcwrappednativejsops.cpp \
xpcwrappednativeproto.cpp \
xpcwrappednativescope.cpp
xpcwrappednativescope.cpp \
$(NULL)
ifdef XPC_IDISPATCH_SUPPORT
CPPSRCS += XPCDispObject.cpp \
XPCDispInterface.cpp \
XPCDispConvert.cpp \
XPCDispTypeInfo.cpp \
XPCDispTearOff.cpp \
XPCIDispatchExtension.cpp
XPCIDispatchExtension.cpp \
XPCDispParams.cpp \
XPCDispParamPropJSClass.cpp \
nsDispatchSupport.cpp \
$(NULL)
endif
CPPSRCS += $(NULL)
include $(topsrcdir)/config/config.mk
@ -119,6 +123,10 @@ endif
ifdef XPC_IDISPATCH_SUPPORT
DEFINES += -DXPC_IDISPATCH_SUPPORT
ifdef XPC_COMOBJECT
DEFINES += -DXPC_COMOBJECT
endif
endif
ifeq ($(OS_ARCH),WINNT)

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

@ -1,4 +1,5 @@
/* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
@ -76,7 +77,7 @@ VARTYPE XPCDispConvert::JSTypeToCOMType(XPCCallContext& ccx, jsval val)
}
JSBool XPCDispConvert::JSArrayToCOMArray(XPCCallContext& ccx, JSObject *obj,
VARIANT & var, uintN& err)
VARIANT & var, nsresult& err)
{
err = NS_OK;
jsuint len;
@ -89,7 +90,7 @@ JSBool XPCDispConvert::JSArrayToCOMArray(XPCCallContext& ccx, JSObject *obj,
SAFEARRAY * array = SafeArrayCreateVector(VT_VARIANT, 0, len);
for(long index = 0; index < len; ++index)
{
VARIANT arrayVar;
_variant_t arrayVar;
jsval val;
if(JS_GetElement(ccx, obj, index, &val) &&
JSToCOM(ccx, val, arrayVar, err))
@ -113,7 +114,7 @@ JSBool XPCDispConvert::JSArrayToCOMArray(XPCCallContext& ccx, JSObject *obj,
JSBool XPCDispConvert::JSToCOM(XPCCallContext& ccx,
jsval src,
VARIANT & dest,
uintN& err)
nsresult& err)
{
err = NS_OK;
if(JSVAL_IS_STRING(src))
@ -191,8 +192,9 @@ JSBool XPCDispConvert::JSToCOM(XPCCallContext& ccx,
return JS_TRUE;
}
JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx, const VARIANT & src,
jsval & dest,uintN& err)
JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx,
const _variant_t & src,
jsval & dest, nsresult& err)
{
err = NS_OK;
// We only support one dimensional arrays for now
@ -214,7 +216,7 @@ JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx, const VARIANT & sr
err = NS_ERROR_OUT_OF_MEMORY;
}
// Devine the type of our array
VARIANT var;
_variant_t var;
if((src.vt & VT_ARRAY) != 0)
{
var.vt = src.vt & ~VT_ARRAY;
@ -240,12 +242,34 @@ JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx, const VARIANT & sr
return JS_TRUE;
}
JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const VARIANT & src,
jsval & dest,uintN& err)
inline
jsval NumberToJSVal(JSContext* cx, int value)
{
jsval val;
if (INT_FITS_IN_JSVAL(value))
val = INT_TO_JSVAL(value);
else
{
if (!JS_NewDoubleValue(cx, NS_STATIC_CAST(jsdouble,value), &val))
val = JSVAL_ZERO;
}
return val;
}
inline
jsval NumberToJSVal(JSContext* cx, double value)
{
jsval val;
if (JS_NewDoubleValue(cx, NS_STATIC_CAST(jsdouble, value), &val))
return val;
else
return JSVAL_ZERO;
}
JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const _variant_t & src,
jsval& dest, nsresult& err)
{
err = NS_OK;
int x = VT_BSTR;
int y = VT_BYREF;
if(src.vt & VT_ARRAY || src.vt == VT_SAFEARRAY)
{
return COMArrayToJSArray(ccx, src, dest, err);
@ -269,7 +293,7 @@ JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const VARIANT & src,
break;
case VT_I4:
{
dest = INT_TO_JSVAL(src.lVal);
dest = NumberToJSVal(ccx, src.lVal);
}
break;
case VT_UI1:
@ -284,12 +308,12 @@ JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const VARIANT & src,
break;
case VT_R4:
{
dest = DOUBLE_TO_JSVAL(NS_STATIC_CAST(float,src.fltVal));
dest = NumberToJSVal(ccx, src.fltVal);
}
break;
case VT_R8:
{
dest = DOUBLE_TO_JSVAL(src.dblVal);
dest = NumberToJSVal(ccx, src.dblVal);
}
break;
case VT_BOOL:
@ -311,7 +335,6 @@ JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const VARIANT & src,
case VT_CY:
case VT_DATE:
case VT_UNKNOWN:
case VT_ARRAY:
case VT_I1:
case VT_UI2:
case VT_UI4:

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

@ -1,4 +1,5 @@
/* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
@ -46,13 +47,6 @@ PRBool nsXPConnect::IsIDispatchEnabled()
return XPCIDispatchExtension::IsEnabled();
}
// XPCDispObject inlines
inline
void XPCDispObject::CleanupVariant(VARIANT & var)
{
VariantClear(&var);
}
// XPCDispInterface inlines
inline
@ -63,11 +57,10 @@ XPCDispInterface::Member::ParamInfo::ParamInfo(
inline
JSBool XPCDispInterface::Member::ParamInfo::InitializeOutputParam(
char * varBuffer, VARIANT & var) const
void * varBuffer, VARIANT & var) const
{
var.vt = GetType() | VT_BYREF;
// TODO: This is a bit hacky, but we just pick one of the pointer types;
var.byref = NS_REINTERPRET_CAST(BSTR*,varBuffer);
var.byref = varBuffer;
return JS_TRUE;
}
@ -81,7 +74,7 @@ PRBool XPCDispInterface::Member::ParamInfo::IsFlagSet(
inline
PRBool XPCDispInterface::Member::ParamInfo::IsIn() const
{
return IsFlagSet(PARAMFLAG_FIN);
return IsFlagSet(PARAMFLAG_FIN) || mParamInfo->paramdesc.wParamFlags == 0;
}
inline
@ -165,19 +158,19 @@ PRBool XPCDispInterface::Member::IsFlagSet(unsigned short flag) const
inline
PRBool XPCDispInterface::Member::IsSetter() const
{
return IsFlagSet(GET_PROPERTY);
return IsFlagSet(SET_PROPERTY);
}
inline
PRBool XPCDispInterface::Member::IsGetter() const
{
return IsFlagSet(SET_PROPERTY);
return IsFlagSet(GET_PROPERTY);
}
inline
PRBool XPCDispInterface::Member::IsProperty() const
{
return IsFlagSet(SET_PROPERTY) || IsFlagSet(GET_PROPERTY);
return IsSetter() || IsGetter();
}
inline
@ -186,6 +179,12 @@ PRBool XPCDispInterface::Member::IsFunction() const
return IsFlagSet(FUNCTION);
}
inline
PRBool XPCDispInterface::Member::IsParameterizedProperty() const
{
return (IsSetter() && GetParamCount() > 1) || (IsGetter() && GetParamCount() > 0);
}
inline
jsval XPCDispInterface::Member::GetName() const
{
@ -277,7 +276,19 @@ PRUint32 XPCDispInterface::GetMemberCount() const
inline
void XPCDispInterface::operator delete(void * p)
{
free(p);
PR_Free(p);
}
inline
XPCDispInterface::~XPCDispInterface()
{
// Cleanup our members, the first gets cleaned up by the destructor
// We have to cleanup the rest manually. These members are allocated
// as part of the XPCIDispInterface object at the end
for (PRUint32 index = 1; index < GetMemberCount(); ++index)
{
mMembers[index].~Member();
}
}
inline
@ -292,7 +303,7 @@ XPCDispInterface::XPCDispInterface(JSContext* cx,
inline
void * XPCDispInterface::operator new (size_t, PRUint32 members)
{
return malloc(sizeof(XPCDispInterface) + sizeof(Member) * (members - 1));
return PR_Malloc(sizeof(XPCDispInterface) + sizeof(Member) * (members - 1));
}
// XPCDispNameArray inlines
@ -359,9 +370,9 @@ inline
jsval XPCDispIDArray::Item(JSContext* cx, PRUint32 index) const
{
jsval val;
if (!JS_IdToValue(cx,
NS_REINTERPRET_CAST(jsid,
mIDArray.ElementAt(index)), &val))
if(!JS_IdToValue(cx,
NS_REINTERPRET_CAST(jsid,
mIDArray.ElementAt(index)), &val))
return JSVAL_NULL;
return val;
}
@ -410,17 +421,66 @@ nsCString XPCDispTypeInfo::GetNameForDispID(DISPID dispID)
}
inline
const nsIID & XPCDispGUID2nsIID(const struct _GUID & guid, nsIID & iid)
const nsIID & XPCDispGUID2nsIID(const struct _GUID & guid)
{
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsIID), "GUID is not the same as nsIID");
iid = NS_REINTERPRET_CAST(const nsIID &,guid);
return iid;
return NS_REINTERPRET_CAST(const nsIID &,guid);
}
inline
const GUID & XPCDispIID2GUID(const nsIID & iid, struct _GUID & guid)
const GUID & XPCDispIID2GUID(const nsIID & iid)
{
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsIID), "GUID is not the same as IID");
guid = NS_REINTERPRET_CAST(const struct _GUID &, iid);
return guid;
return NS_REINTERPRET_CAST(const struct _GUID &, iid);
}
inline
const nsCID & XPCDispGUID2nsCID(const struct _GUID & guid)
{
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsCID), "GUID is not the same as nsCID");
return NS_REINTERPRET_CAST(const nsCID &,guid);
}
inline
const GUID & XPCDispCID2GUID(const nsCID & iid)
{
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsCID), "GUID is not the same as IID");
return NS_REINTERPRET_CAST(const struct _GUID &, iid);
}
inline
void XPCDispParams::SetNamedPropID()
{
mDispParams.rgdispidNamedArgs = &mPropID;
mDispParams.cNamedArgs = 1;
}
inline
VARIANT & XPCDispParams::GetParamRef(PRUint32 index)
{
NS_ASSERTION(index < mDispParams.cArgs, "XPCDispParams::GetParam bounds error");
return mDispParams.rgvarg[mDispParams.cArgs - index - 1];
}
inline
_variant_t XPCDispParams::GetParam(PRUint32 index) const
{
return NS_CONST_CAST(XPCDispParams*,this)->GetParamRef(index);
}
inline
void * XPCDispParams::GetOutputBuffer(PRUint32 index)
{
NS_ASSERTION(index < mDispParams.cArgs, "XPCDispParams::GetParam bounds error");
return mVarBuffer + VARIANT_UNION_SIZE * index;
}
inline
JSBool XPCDispParamPropJSClass::Invoke(XPCCallContext& ccx,
XPCDispObject::CallMode mode,
jsval* retval)
{
return XPCDispObject::Dispatch(ccx, mDispObj, mDispID, mode, mDispParams,
retval);
}

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

@ -1,4 +1,5 @@
/* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
@ -40,6 +41,7 @@
*/
#include "xpcprivate.h"
#include <MBSTRING.H>
/**
* Is this function reflectable
@ -198,6 +200,46 @@ void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, P
}
}
inline
PRUnichar* JSString2PRUnichar(XPCCallContext& ccx, jsval val, size_t* length)
{
JSString* str = JS_ValueToString(ccx, val);
if(!str)
return nsnull;
*length = JS_GetStringLength(str);
PRUnichar * string = NS_REINTERPRET_CAST(PRUnichar*,JS_GetStringChars(str));
return string;
}
inline
PRBool CaseInsensitiveCompare(XPCCallContext& ccx, const PRUnichar* lhs, size_t lhsLength, jsval rhs)
{
size_t rhsLength;
PRUnichar* rhsString = JSString2PRUnichar(ccx, rhs, &rhsLength);
return rhsString &&
lhsLength == rhsLength &&
_wcsnicmp(lhs, rhsString, lhsLength * sizeof(PRUnichar)) == 0;
}
const XPCDispInterface::Member* XPCDispInterface::FindMemberCI(XPCCallContext& ccx, jsval name) const
{
size_t nameLength;
PRUnichar* sName = JSString2PRUnichar(ccx, name, &nameLength);
if(!sName)
return nsnull;
// Iterate backwards to save time
const Member* member = mMembers + mMemberCount;
while(member > mMembers)
{
--member;
if(CaseInsensitiveCompare(ccx, sName, nameLength, member->GetName()))
{
return member;
}
}
return nsnull;
}
JSBool XPCDispInterface::Member::GetValue(XPCCallContext& ccx,
XPCNativeInterface * iface,
jsval * retval) const
@ -216,7 +258,8 @@ JSBool XPCDispInterface::Member::GetValue(XPCCallContext& ccx,
intN argc;
intN flags;
JSNative callback;
if(IsFunction())
// Is this a function or a parameterized getter/setter
if(IsFunction() || IsParameterizedProperty())
{
argc = GetParamCount();
flags = 0;

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

@ -1,4 +1,5 @@
/* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
@ -67,11 +68,51 @@ XPCDispObject::COMCreateFromIDispatch(IDispatch *pDispatch, JSContext *cx, JSObj
return PR_TRUE;
}
IDispatch * XPCDispObject::COMCreateInstance(const char * className)
static boolean HasSafeScriptingCategory(const GUID & classID)
{
CComPtr<ICatInformation> catInfo;
HRESULT hr = catInfo.CoCreateInstance(CLSID_StdComponentCategoriesMgr);
if (catInfo == NULL)
{
// Must fail if we can't open the category manager
return false;
}
// See what categories the class implements
CComPtr<IEnumCATID> enumCATID;
if (FAILED(catInfo->EnumImplCategoriesOfClass(classID, &enumCATID)))
{
// Can't enumerate classes in category so fail
return false;
}
// Search for matching categories
BOOL bFound = FALSE;
CATID catidNext = GUID_NULL;
while (enumCATID->Next(1, &catidNext, NULL) == S_OK)
{
if (::IsEqualCATID(CATID_SafeForScripting, catidNext))
{
bFound = TRUE;
}
}
if (!bFound)
{
return false;
}
return true;
}
inline
boolean ScriptOK(DWORD value)
{
return value & (INTERFACESAFE_FOR_UNTRUSTED_CALLER |
INTERFACESAFE_FOR_UNTRUSTED_DATA);
}
nsresult XPCDispObject::COMCreateInstance(const char * className, PRBool testScriptability, IDispatch ** result)
{
// TODO: This needs to have some error handling. We could probably
// capture some information from the GetLastError
// allows us to convert to BSTR for CLSID functions below
_bstr_t bstrName(className);
CLSID classID;
HRESULT hr;
@ -84,27 +125,129 @@ IDispatch * XPCDispObject::COMCreateInstance(const char * className)
{
hr = CLSIDFromProgID(bstrName, &classID);
}
if(SUCCEEDED(hr))
if(FAILED(hr))
return hr;
PRBool scriptableOK = testScriptability;
if (testScriptability)
{
IDispatch * pDisp;
hr = CoCreateInstance(
classID,
0,
CLSCTX_INPROC_SERVER,
IID_IDispatch,
(LPVOID*)&pDisp);
if(SUCCEEDED(hr))
{
pDisp->AddRef();
return pDisp;
}
const DWORD scriptOk = INTERFACESAFE_FOR_UNTRUSTED_CALLER |
INTERFACESAFE_FOR_UNTRUSTED_DATA;
scriptableOK = HasSafeScriptingCategory(classID);
}
return nsnull;
// Didn't have the safe for scripting category so lets look at IObjectSafety
CComPtr<IDispatch> disp;
if (scriptableOK || !testScriptability)
{
HRESULT hResult = disp.CoCreateInstance(classID);
if (FAILED(hResult))
return hResult;
}
// If we're testing scriptability and it didn't have a scripting category
// we'll check via the IObjectSafety interface
if (testScriptability && !scriptableOK)
{
CComQIPtr<IObjectSafety> objSafety(disp);
// Didn't have IObjectSafety so we'll bail
if (objSafety == 0)
return E_FAIL;
DWORD supported;
DWORD state;
hr = objSafety->GetInterfaceSafetyOptions(IID_IDispatch, &supported, &state);
if (FAILED(hr))
return hr;
if (!ScriptOK(supported) || !ScriptOK(state))
return E_FAIL;
}
disp.CopyTo(result);
return S_OK;
}
// static
JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
DISPID dispID, CallMode mode,
XPCDispParams & params,
jsval* retval,
XPCDispInterface::Member * member,
XPCJSRuntime* rt)
{
// avoid deadlock in case the native method blocks somehow
AutoJSSuspendRequest req(ccx); // scoped suspend of request
_variant_t dispResult;
jsval val;
uintN err;
uintN argc = params.GetParamCount();
WORD dispFlags;
if(mode == CALL_SETTER)
{
dispFlags = DISPATCH_PROPERTYPUT;
}
else if(mode == CALL_GETTER)
{
dispFlags = DISPATCH_PROPERTYGET;
}
else
{
dispFlags = DISPATCH_METHOD;
}
HRESULT invokeResult= disp->Invoke(
dispID, // IDispatch ID
IID_NULL, // Reserved must be IID_NULL
LOCALE_SYSTEM_DEFAULT, // The locale context, use the system's
dispFlags, // Type of Invoke call
params.GetDispParams(), // Parameters
&dispResult, // Where the result is stored
nsnull, // Exception information
0); // Index of an argument error
if(SUCCEEDED(invokeResult))
{
if(mode == CALL_METHOD)
{
NS_ASSERTION(member, "member must not be null if this is a method");
for(PRUint32 index = 0; index < argc; ++index)
{
const XPCDispInterface::Member::ParamInfo & paramInfo = member->GetParamInfo(index);
if(paramInfo.IsOut())
{
if(!XPCDispConvert::COMToJS(ccx, params.GetParamRef(index), val, err))
return ThrowBadParam(err, index, ccx);
if(paramInfo.IsRetVal())
{
*retval = val;
}
else
{
// we actually assured this before doing the invoke
NS_ASSERTION(JSVAL_IS_OBJECT(val), "out var is not an object");
if(!OBJ_SET_PROPERTY(ccx, JSVAL_TO_OBJECT(val),
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &val))
return ThrowBadParam(NS_ERROR_XPC_CANT_SET_OUT_VAL, index, ccx);
}
}
}
}
if(dispResult.vt != VT_EMPTY)
{
if(!XPCDispConvert::COMToJS(ccx, dispResult, val, err))
{
ThrowBadParam(err, 0, ccx);
}
*retval = val;
}
}
ccx.GetXPCContext()->SetLastResult(invokeResult);
if(NS_FAILED(invokeResult))
{
XPCThrower::ThrowCOMError(ccx, invokeResult);
return JS_FALSE;
}
return JS_TRUE;
}
// This is the size of the largest member in the union in VARIANT
const PRUint32 VARIANT_UNION_SIZE = sizeof(VARIANT) - sizeof(VARTYPE) - sizeof(unsigned short) * 3;
#define VARIANT_BUFFER_SIZE(count) (VARIANT_UNION_SIZE * count)
JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
{
@ -119,7 +262,6 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
return Throw(rv, ccx);
}
JSBool retval = JS_FALSE;
// TODO: Remove type cast and change GetIDispatchMember to use the correct type
XPCDispInterface::Member* member = NS_REINTERPRET_CAST(XPCDispInterface::Member*,ccx.GetIDispatchMember());
XPCJSRuntime* rt = ccx.GetRuntime();
@ -134,8 +276,6 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
// set up the method index and do the security check if needed
PRBool setter;
PRBool getter;
PRUint32 secFlag;
PRUint32 secAction;
@ -144,19 +284,14 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
case CALL_METHOD:
secFlag = nsIXPCSecurityManager::HOOK_CALL_METHOD;
secAction = nsIXPCSecurityManager::ACCESS_CALL_METHOD;
getter = setter = PR_FALSE;
break;
case CALL_GETTER:
secFlag = nsIXPCSecurityManager::HOOK_GET_PROPERTY;
secAction = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
setter = PR_FALSE;
getter = PR_TRUE;
break;
case CALL_SETTER:
secFlag = nsIXPCSecurityManager::HOOK_SET_PROPERTY;
secAction = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
setter = PR_TRUE;
getter = PR_FALSE;
break;
default:
NS_ASSERTION(0,"bad value");
@ -181,155 +316,81 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
uintN err;
// TODO: I'm not sure why we need to do this I would have expected COM
// to report one parameter
if(setter)
if(mode == CALL_SETTER)
args = 1;
if(argc < args)
args = argc;
const PRUint32 DEFAULT_ARG_ARRAY_SIZE = 8;
VARIANT stackArgs[DEFAULT_ARG_ARRAY_SIZE];
char varStackBuffer[VARIANT_BUFFER_SIZE(DEFAULT_ARG_ARRAY_SIZE)];
char * varBuffer = args <= DEFAULT_ARG_ARRAY_SIZE ? varStackBuffer : new char[VARIANT_BUFFER_SIZE(args)];
memset(varBuffer, 0, VARIANT_BUFFER_SIZE(args));
VARIANT dispResult;
DISPPARAMS dispParams;
dispParams.cArgs = args;
dispParams.rgvarg = args <= DEFAULT_ARG_ARRAY_SIZE ? stackArgs : new VARIANT[args];
DISPID propID;
XPCDispParams params(args);
jsval val;
// If this is a setter, we just need to convert the first parameter
if(setter)
if(mode == CALL_SETTER)
{
propID = DISPID_PROPERTYPUT;
dispParams.rgdispidNamedArgs = &propID;
dispParams.cNamedArgs = 1;
if(!XPCDispConvert::JSToCOM(ccx, argv[0],dispParams.rgvarg[0], err))
params.SetNamedPropID();
if(!XPCDispConvert::JSToCOM(ccx, argv[0],params.GetParamRef(0), err))
return ThrowBadParam(err, 0, ccx);
}
else if(getter)
else if(mode != CALL_GETTER)
{
dispParams.rgdispidNamedArgs = 0;
dispParams.cNamedArgs = 0;
}
else
{
dispParams.cNamedArgs = 0;
dispParams.rgdispidNamedArgs = 0;
VARIANT* pVar = dispParams.rgvarg + args - 1;
for(PRUint32 index = 0; index < args; ++index, --pVar)
for(PRUint32 index = 0; index < args; ++index)
{
const XPCDispInterface::Member::ParamInfo & paramInfo = member->GetParamInfo(index);
if(paramInfo.IsIn())
{
jsval val = argv[index];
val = argv[index];
if(paramInfo.IsOut())
{
if(JSVAL_IS_PRIMITIVE(argv[index]) ||
!OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[index]),
if(JSVAL_IS_PRIMITIVE(val) ||
!OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(val),
rt->GetStringID(XPCJSRuntime::IDX_VALUE),
&val))
{
ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, index, ccx);
}
}
if(!XPCDispConvert::JSToCOM(ccx, val,*pVar, err))
if(!XPCDispConvert::JSToCOM(ccx, val,params.GetParamRef(index), err))
{
ThrowBadParam(err, index, ccx);
}
}
else
{
paramInfo.InitializeOutputParam(varBuffer + VARIANT_UNION_SIZE * index, *pVar);
paramInfo.InitializeOutputParam(params.GetOutputBuffer(index), params.GetParamRef(index));
}
}
}
HRESULT invokeResult = E_FAIL;
// If this is a parameterized property
if(member->IsParameterizedProperty())
{
// avoid deadlock in case the native method blocks somehow
AutoJSSuspendRequest req(ccx); // scoped suspend of request
IDispatch * pDisp;
// TODO: I'm not sure this QI is really needed
nsresult result = pObj->QueryInterface(NSID_IDISPATCH, (void**)&pDisp);
if(NS_SUCCEEDED(result))
// We need to get a parameterized property object to return to JS
if(XPCDispParamPropJSClass::GetNewOrUsed(ccx, wrapper,
member->GetDispID(),
params, &val))
{
WORD dispFlags;
if(setter)
{
dispFlags = DISPATCH_PROPERTYPUT;
}
else if(getter)
{
dispFlags = DISPATCH_PROPERTYGET;
}
else
{
dispFlags = DISPATCH_METHOD;
}
invokeResult= pDisp->Invoke(member->GetDispID(), IID_NULL, LOCALE_SYSTEM_DEFAULT, dispFlags, &dispParams, &dispResult, 0, 0);
if(SUCCEEDED(invokeResult))
{
if(!setter && !getter)
{
VARIANT* pVar = dispParams.rgvarg + args - 1;
for(PRUint32 index = 0; index < args; ++index, --pVar)
{
const XPCDispInterface::Member::ParamInfo & paramInfo = member->GetParamInfo(index);
if(paramInfo.IsOut())
{
if(paramInfo.IsRetVal())
{
if(!ccx.GetReturnValueWasSet())
ccx.SetRetVal(argv[index]);
}
else
{
jsval val;
if(!XPCDispConvert::COMToJS(ccx, *pVar, val, err))
ThrowBadParam(err, index, ccx);
// we actually assured this before doing the invoke
NS_ASSERTION(JSVAL_IS_OBJECT(argv[index]), "out var is not object");
if(!OBJ_SET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[index]),
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &val))
ThrowBadParam(NS_ERROR_XPC_CANT_SET_OUT_VAL, index, ccx);
}
CleanupVariant(*pVar);
}
}
}
if(!ccx.GetReturnValueWasSet())
{
if(dispResult.vt != VT_EMPTY)
{
jsval val;
if(!XPCDispConvert::COMToJS(ccx, dispResult, val, err))
{
ThrowBadParam(err, 0, ccx);
}
ccx.SetRetVal(val);
}
else if(setter)
{
ccx.SetRetVal(argv[0]);
}
}
retval = JS_TRUE;
}
ccx.SetRetVal(val);
if(!JS_IdToValue(ccx, 1, &val))
return JS_FALSE;
JS_SetCallReturnValue2(ccx, val);
return JS_TRUE;
}
return JS_FALSE;
}
// TODO: I think this needs to be moved up, to only occur if invoke is actually called.
xpcc->SetLastResult(invokeResult);
if(NS_FAILED(invokeResult))
IDispatch * pDisp;
// TODO: I'm not sure this QI is really needed
nsresult result = pObj->QueryInterface(NSID_IDISPATCH, (void**)&pDisp);
if(NS_SUCCEEDED(result))
{
XPCThrower::ThrowCOMError(ccx, invokeResult);
JSBool retval = Dispatch(ccx, pDisp, member->GetDispID(), mode, params, &val, member, rt);
if(retval && mode == CALL_SETTER)
{
ccx.SetRetVal(argv[0]);
}
else
{
ccx.SetRetVal(val);
}
return retval;
}
for(PRUint32 index = 0; index < args; ++index)
CleanupVariant(dispParams.rgvarg[index]);
// Cleanup if we allocated the variant array
if(dispParams.rgvarg != stackArgs)
delete [] dispParams.rgvarg;
if(varBuffer != varStackBuffer)
delete [] varBuffer;
return retval;
return JS_FALSE;
}
/**
@ -381,10 +442,16 @@ JSBool GetMember(XPCCallContext& ccx, JSObject* funobj, XPCNativeInterface*& ifa
* Callback for functions
* This callback is called by JS when a function on a JSObject proxying
* for an IDispatch instance
* @param cx A pointer to a JS context
* @param obj JS object that the parameterized property is on
* @param argc Number of arguments in this call
* @param argv The parameters passed in if any
* @param vp The return value
* @return Returns JS_TRUE if the operation succeeded
*/
JSBool JS_DLL_CALLBACK
XPC_IDispatch_CallMethod(JSContext* cx, JSObject* obj,
uintN argc, jsval* argv, jsval* vp)
XPC_IDispatch_CallMethod(JSContext* cx, JSObject* obj, uintN argc,
jsval* argv, jsval* vp)
{
NS_ASSERTION(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION, "bad function");
JSObject* funobj = JSVAL_TO_OBJECT(argv[-2]);
@ -408,10 +475,16 @@ XPC_IDispatch_CallMethod(JSContext* cx, JSObject* obj,
* Callback for properties
* This callback is called by JS when a property is set or retrieved on a
* JSObject proxying for an IDispatch instance
* @param cx A pointer to a JS context
* @param obj JS object that the parameterized property is on
* @param argc Number of arguments in this call
* @param argv The parameters passed in if any
* @param vp The return value
* @return Returns JS_TRUE if the operation succeeded
*/
JSBool JS_DLL_CALLBACK
XPC_IDispatch_GetterSetter(JSContext *cx, JSObject *obj,
uintN argc, jsval *argv, jsval *vp)
XPC_IDispatch_GetterSetter(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *vp)
{
NS_ASSERTION(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION, "bad function");
JSObject* funobj = JSVAL_TO_OBJECT(argv[-2]);

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

@ -0,0 +1,196 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the IDispatch implementation for XPConnect
*
* The Initial Developer of the Original Code is
* David Bradley.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/** \file XPCDispParamPropJSClass.cpp
* Implementation for the XPCDispParamPropJSClass class
* This file contains the implementation of the XPCDispParamPropJSClass class
*/
#include "xpcprivate.h"
inline
XPCDispParamPropJSClass* GetParamProp(JSContext* cx, JSObject* obj)
{
return NS_REINTERPRET_CAST(XPCDispParamPropJSClass*,
JS_GetPrivate(cx, obj));
}
/**
* Handles getting a property via a parameterized property.
* This object is used as part of the parameterized property mechanism.
* property get requests are forward to our owner and on to IDispatch's
* Invoke
* @param cx A pointer to a JS context
* @param obj The object to perform the get on
* @param id ID of the parameter to get
* @param vp Pointer to the return value
* @return JSBool JS_TRUE if property was retrieved
*/
JS_STATIC_DLL_CALLBACK(JSBool)
XPC_PP_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
XPCDispParamPropJSClass* paramProp = GetParamProp(cx, obj);
JSObject* originalObj = paramProp->GetWrapper()->GetFlatJSObject();
XPCCallContext ccx(JS_CALLER, cx, originalObj, nsnull, id,
paramProp->GetParams().GetParamCount(), nsnull, vp);
return paramProp->Invoke(ccx, XPCDispObject::CALL_GETTER, vp);
}
/**
* Handles getting a property via a parameterized property.
* This object is used as part of the parameterized property mechanism.
* property get requests are forward to our owner and on to IDispatch's
* Invoke
* @param cx A pointer to a JS context
* @param obj The object to perform the get on
* @param id ID of the parameter to get
* @param vp Pointer to the return value
* @return JSBool JS_TRUE if property was retrieved
*/
JS_STATIC_DLL_CALLBACK(JSBool)
XPC_PP_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
XPCDispParamPropJSClass* paramProp = GetParamProp(cx, obj);
JSObject* originalObj = paramProp->GetWrapper()->GetFlatJSObject();
XPCCallContext ccx(JS_CALLER, cx, originalObj, nsnull, id,
paramProp->GetParams().GetParamCount(), nsnull, vp);
_variant_t var;
uintN err;
if(!XPCDispConvert::JSToCOM(ccx, *vp, var, err))
return JS_FALSE;
XPCDispParams& params = paramProp->GetParams();
params.SetNamedPropID();
// params will own var
params.InsertParam(var);
return paramProp->Invoke(ccx, XPCDispObject::CALL_SETTER, vp);
}
/**
* Handles getting a property via a parameterized property.
* This object is used as part of the parameterized property mechanism.
* property get requests are forward to our owner and on to IDispatch's
* Invoke
* @param cx A pointer to a JS context
* @param obj The object to perform the get on
* @param id ID of the parameter to get
* @param vp Pointer to the return value
* @return JSBool JS_TRUE if property was retrieved
*/
JS_STATIC_DLL_CALLBACK(void)
XPC_PP_Finalize(JSContext *cx, JSObject *obj)
{
delete GetParamProp(cx, obj);
}
JS_STATIC_DLL_CALLBACK(uint32)
XPC_PP_Mark(JSContext *cx, JSObject *obj, void *arg)
{
XPCDispParamPropJSClass* paramProp = GetParamProp(cx, obj);
if(paramProp)
{
XPCWrappedNative* wrapper = paramProp->GetWrapper();
if(wrapper && wrapper->IsValid())
xpc_MarkForValidWrapper(cx, wrapper, arg);
}
return 0;
}
static JSClass ParamPropClass = {
"XPCDispParamPropJSCass", // Name
JSCLASS_HAS_PRIVATE, // flags
/* Mandatory non-null function pointer members. */
JS_PropertyStub, // addProperty
JS_PropertyStub, // delProperty
XPC_PP_GetProperty, // getProperty
XPC_PP_SetProperty, // setProperty
JS_EnumerateStub, // enumerate
JS_ResolveStub, // resolve
JS_ConvertStub, // convert
XPC_PP_Finalize, // finalize
/* Optionally non-null members start here. */
nsnull, // getObjectOps;
nsnull, // checkAccess;
nsnull, // call;
nsnull, // construct;
nsnull, // xdrObject;
nsnull, // hasInstance;
XPC_PP_Mark, // mark;
nsnull // spare;
};
// static
JSBool XPCDispParamPropJSClass::GetNewOrUsed(XPCCallContext& ccx,
XPCWrappedNative* wrapper,
PRUint32 dispID,
XPCDispParams& dispParams,
jsval* paramPropObj)
{
XPCDispParamPropJSClass* pDispParam =
new XPCDispParamPropJSClass(wrapper, ccx.GetTearOff()->GetNative(),
dispID, dispParams);
if(!pDispParam)
return JS_FALSE;
JSObject * obj = JS_NewObject(ccx, &ParamPropClass, nsnull, nsnull);
if(!obj)
return JS_FALSE;
if(!JS_SetPrivate(ccx, obj, pDispParam))
return JS_FALSE;
*paramPropObj = OBJECT_TO_JSVAL(obj);
return JS_TRUE;
}
XPCDispParamPropJSClass::XPCDispParamPropJSClass(XPCWrappedNative* wrapper,
nsISupports * dispObj,
PRUint32 dispID,
XPCDispParams& dispParams) :
mWrapper(wrapper),
mDispID(dispID),
mDispParams(dispParams)
{
nsresult result = dispObj->QueryInterface(NSID_IDISPATCH,
NS_REINTERPRET_CAST(void**,
&mDispObj));
if(NS_FAILED(result))
mDispObj = nsnull;
}
XPCDispParamPropJSClass::~XPCDispParamPropJSClass()
{
mDispObj->Release();
}

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

@ -0,0 +1,115 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the IDispatch implementation for XPConnect
*
* The Initial Developer of the Original Code is
* David Bradley.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "xpcprivate.h"
XPCDispParams::XPCDispParams(PRUint32 args) :
mVarBuffer(args <= DEFAULT_ARG_ARRAY_SIZE ?
mVarStackBuffer : new char[XPC_VARIANT_BUFFER_SIZE(args)]),
mPropID(DISPID_PROPERTYPUT)
{
memset(mVarBuffer, 0, XPC_VARIANT_BUFFER_SIZE(args));
// Initialize the IDispatch parameters
mDispParams.cArgs = args;
mDispParams.rgvarg = args <= DEFAULT_ARG_ARRAY_SIZE ? mStackArgs : new VARIANT[args];
mDispParams.rgdispidNamedArgs = nsnull;
mDispParams.cNamedArgs = 0;
}
// This transfers the variants, it does not copy
XPCDispParams::XPCDispParams(XPCDispParams & other) :
mPropID(DISPID_PROPERTYPUT)
{
mDispParams.rgdispidNamedArgs = nsnull;
mDispParams.cNamedArgs = 0;
mDispParams.cArgs = other.mDispParams.cArgs;
if(other.mVarBuffer == other.mVarStackBuffer)
{
mVarBuffer = mVarStackBuffer;
memcpy(mVarBuffer, other.mVarBuffer,
XPC_VARIANT_BUFFER_SIZE(other.mDispParams.cArgs));
}
else
{
mVarBuffer = other.mVarBuffer;
other.mVarBuffer = nsnull;
}
if(other.mDispParams.rgvarg == other.mStackArgs)
{
mDispParams.rgvarg = mStackArgs;
memcpy(mDispParams.rgvarg, other.mStackArgs,
sizeof(VARIANT) * other.mDispParams.cArgs);
other.mDispParams.cArgs;
}
else
{
mDispParams.rgvarg = other.mDispParams.rgvarg;
other.mDispParams.rgvarg = 0;
}
other.mDispParams.cArgs = 0;
}
XPCDispParams::~XPCDispParams()
{
for(PRUint32 index = 0; index < mDispParams.cArgs; ++index)
VariantClear(mDispParams.rgvarg + index);
// Cleanup if we allocated the variant array
if(mDispParams.rgvarg != mStackArgs)
delete [] mDispParams.rgvarg;
if(mVarBuffer != mVarStackBuffer)
delete [] mVarBuffer;
}
void XPCDispParams::InsertParam(_variant_t & var)
{
VARIANT* oldArgs = mDispParams.rgvarg;
char * oldVarBuffer = mVarBuffer;
if(mDispParams.cNamedArgs >= DEFAULT_ARG_ARRAY_SIZE)
{
if(mDispParams.rgvarg == mStackArgs)
mDispParams.rgvarg = new VARIANT[mDispParams.cArgs + 1];
if(mVarBuffer == mVarStackBuffer)
mVarBuffer = new char [XPC_VARIANT_BUFFER_SIZE(mDispParams.cArgs + 1)];
}
// Move the data up, using position save copy
memmove(mDispParams.rgvarg + 1, oldArgs, sizeof(VARIANT) * mDispParams.cArgs);
memmove(mVarBuffer + VARIANT_UNION_SIZE,oldVarBuffer, XPC_VARIANT_BUFFER_SIZE(mDispParams.cArgs));
mDispParams.rgvarg[0] = var.Detach();
memset(mVarBuffer, 0, VARIANT_UNION_SIZE);
++mDispParams.cArgs;
}

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

@ -1,4 +1,5 @@
/* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
@ -41,6 +42,8 @@
#error "DispPrivate.h should not be included directly, please use XPCPrivate.h"
#endif
#include "nsIDispatchSupport.h"
#define NS_DECL_IUNKNOWN \
public: \
STDMETHOD(QueryInterface)(const struct _GUID& aIID, \
@ -109,10 +112,10 @@ public:
* @param src JS Value to convert
* @param dest COM variant to receive the converted value
* @param err receives the error code if any of a failed conversion
* @return Returns true if the conversion succeeded
* @return True if the conversion succeeded
*/
static
JSBool JSToCOM(XPCCallContext& ccx, jsval src, VARIANT & dest, uintN & err);
JSBool JSToCOM(XPCCallContext& ccx, jsval src, VARIANT & dest, nsresult& err);
/**
* Converts a COM variant to a jsval
@ -123,65 +126,31 @@ public:
* @return Returns true if the conversion succeeded
*/
static
JSBool COMToJS(XPCCallContext& ccx, const VARIANT & src, jsval & dest,
uintN & err);
JSBool COMToJS(XPCCallContext& ccx, const _variant_t & src, jsval & dest,
nsresult& err);
private:
/**
* Converts a JS Array to a safe array
* @param ccx XPConnect call context
* @param ccx
*/
static
JSBool JSArrayToCOMArray(XPCCallContext& ccx, JSObject *obj, VARIANT & var,
uintN & err);
nsresult& err);
/**
* Converts a COM Array to a JS Array
*/
static
JSBool COMArrayToJSArray(XPCCallContext& ccx, const VARIANT & src,
jsval & dest,uintN& err);
JSBool COMArrayToJSArray(XPCCallContext& ccx, const _variant_t & src,
jsval & dest, nsresult& err);
};
JSBool JS_DLL_CALLBACK
XPC_IDispatch_CallMethod(JSContext *cx, JSObject *obj,
uintN argc, jsval *argv, jsval *vp);
XPC_IDispatch_CallMethod(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *vp);
JSBool JS_DLL_CALLBACK
XPC_IDispatch_GetterSetter(JSContext *cx, JSObject *obj,
uintN argc, jsval *argv, jsval *vp);
/**
* Used to invoke IDispatch methods
*/
class XPCDispObject
{
public:
enum CallMode {CALL_METHOD, CALL_GETTER, CALL_SETTER};
/**
* Used to invoke an IDispatch method
*/
static
JSBool Invoke(XPCCallContext & ccx, CallMode mode);
/**
* Instantiates a COM object given a class ID or a prog ID
*/
static
IDispatch * COMCreateInstance(const char * className);
/**
* Create a COM object from an existing IDispatch interface (e.g. returned by another object)
*/
static
PRBool COMCreateFromIDispatch(IDispatch *pDispatch, JSContext *cx, JSObject *obj, jsval *rval);
/**
* Throws an error, converting the errNum to an exception
*/
static
JSBool Throw(uintN errNum, JSContext* cx);
/**
* Cleans up a variant if it was allocated
*/
inline
static
void CleanupVariant(VARIANT & var);
};
XPC_IDispatch_GetterSetter(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *vp);
/**
* This class holds an array of names. It indexes based on a *one based* dispid
@ -510,7 +479,7 @@ public:
{
public:
ParamInfo(const ELEMDESC * paramInfo);
JSBool InitializeOutputParam(char * varBuffer,
JSBool InitializeOutputParam(void * varBuffer,
VARIANT & var) const;
/**
* Tests if a specific flag is set
@ -531,7 +500,7 @@ public:
/**
* Placement new is needed to initialize array in class XPCDispInterface
*/
void* operator new(size_t, Member* p);
void* operator new(size_t, Member* p) CPP_THROW_NEW;
PRBool IsSetter() const;
/**
* Returns true if this is a getter
@ -541,6 +510,10 @@ public:
* Returns true if this is a setter
*/
PRBool IsProperty() const;
/**
* Returns true if this is a parameterized property
*/
PRBool IsParameterizedProperty() const;
/**
* Returns true if this is a function
*/
@ -619,17 +592,25 @@ public:
JSObject* GetJSObject() const;
void SetJSObject(JSObject* jsobj);
const Member * FindMember(jsval name) const;
/**
* Looksup a member ignoring case
* @param ccx A call context
* @param name The name of the member
* @return A pointer to a member or nsnull if not found
*/
const Member* FindMemberCI(XPCCallContext& ccx, jsval name) const;
const Member & GetMember(PRUint32 index);
PRUint32 GetMemberCount() const;
static
XPCDispInterface* NewInstance(JSContext* cx, nsISupports * pIface);
void operator delete(void * p);
~XPCDispInterface();
private:
XPCDispInterface(JSContext* cx,
ITypeInfo * pTypeInfo,
PRUint32 members);
void * operator new (size_t, PRUint32 members);
void * operator new (size_t, PRUint32 members) CPP_THROW_NEW;
JSObject* mJSObject;
PRUint32 mMemberCount;
@ -639,6 +620,42 @@ private:
PRUint32 members);
};
/**
* Used to invoke IDispatch methods
*/
class XPCDispObject
{
public:
enum CallMode {CALL_METHOD, CALL_GETTER, CALL_SETTER};
static
JSBool Dispatch(XPCCallContext& ccx, IDispatch * pDisp,
DISPID dispID, CallMode mode, XPCDispParams & params,
jsval* retval, XPCDispInterface::Member* member = nsnull,
XPCJSRuntime* rt = nsnull);
/**
* Used to invoke an IDispatch method
*/
static
JSBool Invoke(XPCCallContext & ccx, CallMode mode);
/**
* Instantiates a COM object given a class ID or a prog ID
*/
static
nsresult COMCreateInstance(const char * className,
PRBool testScriptability, IDispatch ** result);
/**
* Create a COM object from an existing IDispatch interface (e.g. returned by another object)
*/
static
PRBool COMCreateFromIDispatch(IDispatch *pDispatch, JSContext *cx,
JSObject *obj, jsval *rval);
/**
* Throws an error, converting the errNum to an exception
*/
static
JSBool Throw(uintN errNum, JSContext* cx);
};
class XPCIDispatchExtension
{
public:
@ -660,6 +677,85 @@ private:
static PRBool mIsEnabled;
};
class XPCDispParams
{
public:
XPCDispParams(PRUint32 args);
/**
* Makes a copy
* Makes a copy and transfers ownership of buffers
*/
XPCDispParams(XPCDispParams & other);
~XPCDispParams();
void SetNamedPropID();
VARIANT & GetParamRef(PRUint32 index);
_variant_t GetParam(PRUint32 index) const;
void * GetOutputBuffer(PRUint32 index);
DISPPARAMS* GetDispParams() { return &mDispParams; }
uintN GetParamCount() const { return mDispParams.cArgs; }
void InsertParam(_variant_t & var);
private:
XPCDispParams& operator =(const XPCDispParams&) {
NS_ERROR("XPCDispParams can't be assigned"); }
enum
{
DEFAULT_ARG_ARRAY_SIZE = 8,
// This is the size of the largest member in the union in VARIANT
VARIANT_UNION_SIZE = sizeof(VARIANT) - sizeof(VARTYPE) - sizeof(unsigned short) * 3
};
#define XPC_VARIANT_BUFFER_SIZE(count) (VARIANT_UNION_SIZE * count)
DISPPARAMS mDispParams;
char* mVarBuffer;
char mVarStackBuffer[XPC_VARIANT_BUFFER_SIZE(DEFAULT_ARG_ARRAY_SIZE)];
VARIANT mStackArgs[DEFAULT_ARG_ARRAY_SIZE];
DISPID mPropID;
};
/**
* Parameterized property object JSClass
* This class is used to support parameterized properties for IDispatch
*/
class XPCDispParamPropJSClass
{
public:
static JSBool GetNewOrUsed(XPCCallContext& ccx, XPCWrappedNative* wrapper,
PRUint32 dispID,
XPCDispParams& dispParams,
jsval* paramPropObj);
~XPCDispParamPropJSClass();
XPCWrappedNative* GetWrapper() const { return mWrapper; }
JSBool Invoke(XPCCallContext& ccx,
XPCDispObject::CallMode mode,
jsval* retval);
XPCDispParams& GetParams() { return mDispParams; }
private:
XPCDispParamPropJSClass(XPCWrappedNative* wrapper, nsISupports* dispObj,
PRUint32 dispID, XPCDispParams& dispParams);
XPCWrappedNative* mWrapper;
PRUint32 mDispID;
XPCDispParams mDispParams;
IDispatch* mDispObj;
};
class nsDispatchSupport : public nsIDispatchSupport
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDISPATCHSUPPORT
nsDispatchSupport();
virtual ~nsDispatchSupport();
static nsDispatchSupport* GetSingleton();
static void FreeSingleton() { NS_IF_RELEASE(mInstance); }
private:
static nsDispatchSupport* mInstance;
};
#include "XPCDispInlines.h"
#endif

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

@ -1,4 +1,5 @@
/* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
@ -155,8 +156,7 @@ STDMETHODIMP XPCDispatchTearOff::QueryInterface(const struct _GUID & guid,
return NS_OK;
}
nsIID iid;
return mWrappedJS->QueryInterface(XPCDispGUID2nsIID(guid, iid), pPtr);
return mWrappedJS->QueryInterface(XPCDispGUID2nsIID(guid), pPtr);
}
STDMETHODIMP XPCDispatchTearOff::GetTypeInfoCount(unsigned int FAR * pctinfo)
@ -600,7 +600,7 @@ pre_call_clean_up:
{
if((pDispParams->rgvarg[index].vt & VT_BYREF) != 0)
{
XPCDispObject::CleanupVariant(pDispParams->rgvarg[i]);
VariantClear(pDispParams->rgvarg + i);
}
}
}

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

@ -1,4 +1,5 @@
/* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version

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

@ -40,9 +40,9 @@ static const char* const IDISPATCH_NAME = "IDispatch";
PRBool XPCIDispatchExtension::mIsEnabled = PR_TRUE;
JS_STATIC_DLL_CALLBACK(JSBool)
COMObjectConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
static JSBool
CommonConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval, PRBool testScriptability)
{
// Make sure we were called with one string parameter
if(argc != 1 || (argc == 1 && !JSVAL_IS_STRING(argv[0])))
@ -65,12 +65,18 @@ COMObjectConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
}
// Instantiate the desired COM object
IDispatch* pDispatch = XPCDispObject::COMCreateInstance(bytes);
IDispatch* pDispatch = nsnull;;
nsresult rv = XPCDispObject::COMCreateInstance(bytes, testScriptability, &pDispatch);
if (NS_FAILED(rv))
{
// TODO: error reporting
return JS_FALSE;
}
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = nsXPConnect::GetXPConnect()->WrapNative(cx, obj,
rv = nsXPConnect::GetXPConnect()->WrapNative(cx, obj,
NS_REINTERPRET_CAST(nsISupports*, pDispatch),
NSID_IDISPATCH, getter_AddRefs(holder));
if(FAILED(rv) || !holder)
if(FAILED(rv))
{
// TODO: error reporting
return JS_FALSE;
@ -82,33 +88,64 @@ COMObjectConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return JS_TRUE;
}
JS_STATIC_DLL_CALLBACK(JSBool)
COMObjectConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
return CommonConstructor(cx, obj, argc, argv, rval, PR_FALSE);
}
JS_STATIC_DLL_CALLBACK(JSBool)
ActiveXConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
return CommonConstructor(cx, obj, argc, argv, rval, PR_TRUE);
}
JSBool XPCIDispatchExtension::Initialize(JSContext * aJSContext,
JSObject * aGlobalJSObj)
{
// TODO: Cleanup error code
return JS_DefineFunction(aJSContext, aGlobalJSObj, "COMObject",
COMObjectConstructor, 1, 0) ? PR_TRUE : PR_FALSE;
JSBool result = JS_DefineFunction(aJSContext, aGlobalJSObj, "ActiveXObject",
ActiveXConstructor, 1, 0) != nsnull;
#ifdef XPC_COMOBJECT
if (result)
result = JS_DefineFunction(aJSContext, aGlobalJSObj, "COMObject",
COMObjectConstructor, 1, 0) != nsnull;
#endif
return result;
}
JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx, JSObject *obj, jsval idval,
XPCWrappedNative* wrapperToReflectInterfaceNames,
uintN propFlags, JSBool* resolved)
JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx,
JSObject *obj, jsval idval,
XPCWrappedNative* wrapperToReflectInterfaceNames,
uintN propFlags, JSBool* resolved)
{
XPCNativeInterface* iface = XPCNativeInterface::GetNewOrUsed(ccx, "IDispatch");
if (iface == nsnull)
if(iface == nsnull)
return JS_FALSE;
XPCWrappedNativeTearOff* to =
wrapperToReflectInterfaceNames->FindTearOff(ccx, iface, JS_TRUE);
if (to == nsnull)
if(to == nsnull)
return JS_FALSE;
JSObject* jso = to->GetJSObject();
if (jso == nsnull)
if(jso == nsnull)
return JS_FALSE;
const XPCDispInterface::Member * member = to->GetIDispatchInfo()->FindMember(idval);
if (member == nsnull)
if(!JSVAL_IS_STRING(idval))
return JS_FALSE;
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;
}
jsval funval;
if(!member->GetValue(ccx, iface, &funval))
return JS_FALSE;
@ -116,7 +153,7 @@ JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx, JSObject *obj
if(!funobj)
return JS_FALSE;
jsid id;
if (member->IsFunction())
if(member->IsFunction() || member->IsParameterizedProperty())
{
AutoResolveName arn(ccx, idval);
if(resolved)
@ -125,9 +162,9 @@ JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx, JSObject *obj
OBJ_DEFINE_PROPERTY(ccx, obj, id, OBJECT_TO_JSVAL(funobj),
nsnull, nsnull, propFlags, nsnull);
}
NS_ASSERTION(!member || member->IsSetter(), "way broken!");
NS_ASSERTION(member->IsProperty(), "way broken!");
propFlags |= JSPROP_GETTER | JSPROP_SHARED;
if (member->IsSetter())
if(member->IsSetter())
{
propFlags |= JSPROP_SETTER;
propFlags &= ~JSPROP_READONLY;

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

@ -0,0 +1,87 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the IDispatch implementation for XPConnect
*
* The Initial Developer of the Original Code is
* David Bradley.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "XPCPrivate.h"
nsDispatchSupport* nsDispatchSupport::mInstance = nsnull;
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDispatchSupport, nsIDispatchSupport)
nsDispatchSupport::nsDispatchSupport()
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
}
nsDispatchSupport::~nsDispatchSupport()
{
/* destructor code */
}
/* void COMVariant2JSVal (in COMVARIANTPtr comvar, out JSVal val); */
NS_IMETHODIMP nsDispatchSupport::COMVariant2JSVal(VARIANT * comvar, jsval *val)
{
XPCCallContext ccx(NATIVE_CALLER);
nsresult retval;
XPCDispConvert::COMToJS(ccx, *comvar, *val, retval);
return retval;
}
/* void COMArray2JSArray (in COMVARIANTPtr comvar, out JSObjectPtr obj); */
NS_IMETHODIMP nsDispatchSupport::JSVal2COMVariant(jsval val, VARIANT * comvar)
{
XPCCallContext ccx(NATIVE_CALLER);
nsresult retval;
XPCDispConvert::JSToCOM(ccx, val, *comvar, retval);
return retval;
}
NS_IMETHODIMP nsDispatchSupport::CreateInstance(const char * className, PRBool testScriptability, IDispatch ** result)
{
return XPCDispObject::COMCreateInstance(className, testScriptability, result);
}
nsDispatchSupport* nsDispatchSupport::GetSingleton()
{
if(!mInstance)
{
mInstance = new nsDispatchSupport;
NS_IF_ADDREF(mInstance);
}
NS_IF_ADDREF(mInstance);
return mInstance;
}

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

@ -168,6 +168,9 @@ XPCCallContext::SetName(jsval name)
mName = name;
#ifdef XPC_IDISPATCH_SUPPORT
mIDispatchMember = nsnull;
#endif
if(mTearOff)
{
mSet = nsnull;
@ -220,6 +223,9 @@ XPCCallContext::SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member,
if(mState < HAVE_NAME)
mState = HAVE_NAME;
#ifdef XPC_IDISPATCH_SUPPORT
mIDispatchMember = nsnull;
#endif
}
void
@ -476,6 +482,7 @@ XPCCallContext::SetIDispatchInfo(XPCNativeInterface* iface,
mSet = nsnull;
mInterface = iface;
mMember = nsnull;
mIDispatchMember = member;
mName = NS_REINTERPRET_CAST(XPCDispInterface::Member*,member)->GetName();

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

@ -94,6 +94,7 @@ class xpcPropertyBagEnumerator;
// Forwards
class XPCDispInterface;
struct IDispatch;
class XPCDispParams;
#endif

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

@ -563,17 +563,17 @@ inline void XPCNativeSet::ASSERT_NotMarked()
/***************************************************************************/
inline
JSObject* XPCWrappedNativeTearOff::GetJSObject() const
JSObject* XPCWrappedNativeTearOff::GetJSObject() const
{
#ifdef XPC_IDISPATCH_SUPPORT
return IsIDispatch() ? GetIDispatchInfo()->GetJSObject() : mJSObject;
return IsIDispatch() ? GetIDispatchInfo()->GetJSObject() : mJSObject;
#else
return mJSObject;
#endif
}
inline
void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj)
void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj)
{
#ifdef XPC_IDISPATCH_SUPPORT
if(IsIDispatch())
@ -585,27 +585,38 @@ void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj)
#ifdef XPC_IDISPATCH_SUPPORT
inline void
XPCWrappedNativeTearOff::SetIDispatch(JSContext* cx)
XPCWrappedNativeTearOff::SetIDispatch(JSContext* cx)
{
mJSObject = (JSObject*)(((jsword)
::XPCDispInterface::NewInstance(cx,
mNative)) | 2);
::XPCDispInterface::NewInstance(cx,
mNative)) | 2);
}
inline XPCDispInterface*
XPCWrappedNativeTearOff::GetIDispatchInfo() const
XPCWrappedNativeTearOff::GetIDispatchInfo() const
{
return NS_REINTERPRET_CAST(XPCDispInterface*,
(((jsword)mJSObject) & ~JSOBJECT_MASK));
}
inline JSBool
XPCWrappedNativeTearOff::IsIDispatch() const
inline JSBool
XPCWrappedNativeTearOff::IsIDispatch() const
{
return (JSBool)(((jsword)mJSObject) & IDISPATCH_BIT);
}
#endif
inline
XPCWrappedNativeTearOff::~XPCWrappedNativeTearOff()
{
NS_ASSERTION(!(GetInterface()||GetNative()||GetJSObject()), "tearoff not empty in dtor");
#ifdef XPC_IDISPATCH_SUPPORT
if (IsIDispatch())
delete GetIDispatchInfo();
#endif
}
/***************************************************************************/
inline JSBool

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

@ -63,6 +63,10 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIJSRuntimeService, nsJSRuntimeService
NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptError)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPCComponents_Interfaces)
#ifdef XPC_IDISPATCH_SUPPORT
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIDispatchSupport, nsDispatchSupport::GetSingleton)
#endif
NS_DECL_CLASSINFO(nsXPCException)
#ifdef XPCONNECT_STANDALONE
@ -87,6 +91,10 @@ static const nsModuleComponentInfo components[] = {
{ "JS subscript loader", MOZ_JSSUBSCRIPTLOADER_CID,
mozJSSubScriptLoadContractID, mozJSSubScriptLoaderConstructor },
#endif
#ifdef XPC_IDISPATCH_SUPPORT
{ nsnull, NS_IDISPATCH_SUPPORT_CID, NS_IDISPATCH_SUPPORT_CONTRACTID,
nsIDispatchSupportConstructor }
#endif
};
PR_STATIC_CALLBACK(void)
@ -97,6 +105,9 @@ xpcModuleDtor(nsIModule* self)
nsXPCThreadJSContextStackImpl::FreeSingleton();
nsJSRuntimeServiceImpl::FreeSingleton();
xpc_DestroyJSxIDClassObjects();
#ifdef XPC_IDISPATCH_SUPPORT
nsDispatchSupport::FreeSingleton();
#endif
}
NS_IMPL_NSGETMODULE_WITH_DTOR(xpconnect, components, xpcModuleDtor)

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

@ -120,6 +120,7 @@
extern CComModule _Module;
#include <atlcom.h>
#include <atlctl.h>
// MS clutters the global namespace with so many macro names :-(
// I tried to keep these includes in the CPP's but it became too
// convoluted
@ -973,6 +974,10 @@ XPC_WN_GetterSetter(JSContext *cx, JSObject *obj,
extern JSBool
xpc_InitWrappedNativeJSOps();
// Comes from xpcwrappednativeops.cpp
extern void
xpc_MarkForValidWrapper(JSContext *cx, XPCWrappedNative* wrapper, void *arg);
/***************************************************************************/
/***************************************************************************/
@ -1682,12 +1687,11 @@ public:
void SetNative(nsISupports* Native) {mNative = Native;}
void SetJSObject(JSObject* JSObj);
void JSObjectFinalized() {mJSObject = nsnull;}
void JSObjectFinalized() {SetJSObject(nsnull);}
XPCWrappedNativeTearOff()
: mInterface(nsnull), mNative(nsnull), mJSObject(nsnull) {}
~XPCWrappedNativeTearOff()
{NS_ASSERTION(!(GetInterface()||GetNative()||GetJSObject()), "tearoff not empty in dtor");}
~XPCWrappedNativeTearOff();
void Mark() {mJSObject = (JSObject*)(((jsword)mJSObject) | 1);}
void Unmark() {mJSObject = (JSObject*)(((jsword)mJSObject) & ~1);}

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

@ -216,7 +216,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
// in a pointer that hasn't been QI'd to IDispatch properly this could
// create multiple wrappers for the same object, creating a fair bit of
// confusion.
if(!nsXPConnect::IsIDispatchEnabled() && Interface->GetIID()->Equals(NSID_IDISPATCH))
if(nsXPConnect::IsIDispatchEnabled() && Interface->GetIID()->Equals(NSID_IDISPATCH))
identity = Object;
else
#endif
@ -937,6 +937,10 @@ XPCWrappedNative::SystemIsBeingShutDown(XPCCallContext& ccx)
if(to->GetJSObject())
{
JS_SetPrivate(ccx, to->GetJSObject(), nsnull);
#ifdef XPC_IDISPATCH_SUPPORT
if(to->IsIDispatch())
delete to->GetIDispatchInfo();
#endif
to->SetJSObject(nsnull);
}
// We leak the tearoff mNative

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

@ -647,8 +647,8 @@ MarkScopeJSObjects(JSContext *cx, XPCWrappedNativeScope* scope, void *arg)
}
}
static void
MarkForValidWrapper(JSContext *cx, XPCWrappedNative* wrapper, void *arg)
void
xpc_MarkForValidWrapper(JSContext *cx, XPCWrappedNative* wrapper, void *arg)
{
// NOTE: It might be nice to also do the wrapper->Mark() call here too.
// That call marks the wrapper's and wrapper's proto's interface sets.
@ -687,7 +687,7 @@ XPC_WN_Shared_Mark(JSContext *cx, JSObject *obj, void *arg)
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
if(wrapper && wrapper->IsValid())
MarkForValidWrapper(cx, wrapper, arg);
xpc_MarkForValidWrapper(cx, wrapper, arg);
return 1;
}
@ -881,7 +881,7 @@ XPC_WN_Helper_Mark(JSContext *cx, JSObject *obj, void *arg)
if(wrapper && wrapper->IsValid())
{
wrapper->GetScriptableCallback()->Mark(wrapper, cx, obj, arg, &ignored);
MarkForValidWrapper(cx, wrapper, arg);
xpc_MarkForValidWrapper(cx, wrapper, arg);
}
return (uint32) ignored;
}