зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
fe881b976d
Коммит
64676a5373
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче