Back to index

lightning-sunbird  0.9+nobinonly
Static Public Member Functions | Static Private Member Functions
XPCDispConvert Class Reference

JS<>COM Conversion functions. More...

#include <XPCDispPrivate.h>

List of all members.

Static Public Member Functions

static VARTYPE JSTypeToCOMType (XPCCallContext &ccx, jsval val)
 Returns the COM type for a given jsval.
static JSBool JSToCOM (XPCCallContext &ccx, jsval src, VARIANT &dest, nsresult &err, JSBool isByRef=JS_FALSE)
 Converts a JSVal to a COM variant.
static JSBool COMToJS (XPCCallContext &ccx, const VARIANT &src, jsval &dest, nsresult &err)
 Converts a COM variant to a jsval.

Static Private Member Functions

static JSBool JSArrayToCOMArray (XPCCallContext &ccx, JSObject *obj, VARIANT &var, nsresult &err)
 Converts a JS Array to a safe array.
static JSBool COMArrayToJSArray (XPCCallContext &ccx, const VARIANT &src, jsval &dest, nsresult &err)
 Converts a COM Array to a JS Array.

Detailed Description

JS<>COM Conversion functions.

XPCDispConvert serves more as a namespace than a class. It contains the functions to convert between JS and COM data and any helper functions needed

Definition at line 147 of file XPCDispPrivate.h.


Member Function Documentation

JSBool XPCDispConvert::COMArrayToJSArray ( XPCCallContext ccx,
const VARIANT &  src,
jsval dest,
nsresult err 
) [static, private]

Converts a COM Array to a JS Array.

Parameters:
ccxXPConnect call context
srcthe variant holding the array
destthe jsval to receive the array
errreceives the error code if any of a failed conversion
Returns:
True if the conversion succeeded

Definition at line 361 of file XPCDispConvert.cpp.

{
    err = NS_OK;
    // We only support one dimensional arrays for now
    if(SafeArrayGetDim(src.parray) != 1)
    {
        err = NS_ERROR_FAILURE;
        return JS_FALSE;
    }
    // Get the upper bound;
    long ubound;
    if(FAILED(SafeArrayGetUBound(src.parray, 1, &ubound)))
    {
        err = NS_ERROR_FAILURE;
        return JS_FALSE;
    }
    // Get the lower bound
    long lbound;
    if(FAILED(SafeArrayGetLBound(src.parray, 1, &lbound)))
    {
        err = NS_ERROR_FAILURE;
        return JS_FALSE;
    }
    // Create the JS Array
    JSObject * array = JS_NewArrayObject(ccx, ubound - lbound + 1, nsnull);
    if(!array)
    {
        err = NS_ERROR_OUT_OF_MEMORY;
        return JS_FALSE;
    }
    AUTO_MARK_JSVAL(ccx, OBJECT_TO_JSVAL(array));
    // Divine the type of our array
    VARTYPE vartype;
    if((src.vt & VT_ARRAY) != 0)
    {
        vartype = src.vt & ~VT_ARRAY;
    }
    else // This was maybe a VT_SAFEARRAY
    {
        if(FAILED(SafeArrayGetVartype(src.parray, &vartype)))
            return JS_FALSE;
    }
    jsval val = JSVAL_NULL;
    AUTO_MARK_JSVAL(ccx, &val);
    for(long index = lbound; index <= ubound; ++index)
    {
        // Divine the type of our array
        _variant_t var;
        var.vt = vartype;
        if(FAILED(SafeArrayGetElement(src.parray, &index, &var.byref)))
        {
            err = NS_ERROR_FAILURE;
            return JS_FALSE;
        }
        if(!COMToJS(ccx, var, val, err))
            return JS_FALSE;
        JS_SetElement(ccx, array, index, &val);
    }
    dest = OBJECT_TO_JSVAL(array);
    return JS_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool XPCDispConvert::COMToJS ( XPCCallContext ccx,
const VARIANT &  src,
jsval dest,
nsresult err 
) [static]

Converts a COM variant to a jsval.

Parameters:
ccxXPConnect call context
srcCOM variant to convert
destjsval to receive the converted value
errreceives the error code if any of a failed conversion
Returns:
Returns true if the conversion succeeded

Currently unsupported conversion types

Definition at line 446 of file XPCDispConvert.cpp.

{
    err = NS_OK;
    if(src.vt & VT_ARRAY || src.vt == VT_SAFEARRAY)
    {
        return COMArrayToJSArray(ccx, src, dest, err);
    }
    PRBool isPtr = src.vt & VT_BYREF;
    switch (src.vt & ~(VT_BYREF))
    {
        case VT_UINT:
        {
            return JS_NewNumberValue(ccx, VALUE(uintVal), &dest);
        }
        break;
        case VT_UI4:
        {
            return JS_NewNumberValue(ccx, VALUE(ulVal), &dest);
        }
        break;
        case VT_INT:
        {
            return JS_NewNumberValue(ccx, VALUE(intVal), &dest);
        }
        break;
        case VT_I4:
        {
            return JS_NewNumberValue(ccx, VALUE(lVal), &dest);
        }
        break;
        case VT_UI1:
        {
            dest = INT_TO_JSVAL(VALUE(bVal));
        }
        break;
        case VT_I1:
        {
            dest = INT_TO_JSVAL(VALUE(cVal));
        }
        break;
        case VT_UI2:
        {
            dest = INT_TO_JSVAL(VALUE(uiVal));
        }
        break;
        case VT_I2:
        {
            dest = INT_TO_JSVAL(VALUE(iVal));
        }
        break;
        case VT_R4:
        {
            return JS_NewNumberValue(ccx, VALUE(fltVal), &dest);
        }
        break;
        case VT_R8:
        {
            return JS_NewNumberValue(ccx, VALUE(dblVal), &dest);
        }
        break;
        case VT_BOOL:
        {
            dest = BOOLEAN_TO_JSVAL(VALUE(boolVal) != VARIANT_FALSE ? JS_TRUE : JS_FALSE);
        }
        break;
        case VT_DISPATCH:
        {
            XPCDispObject::WrapIDispatch(VALUE(pdispVal), ccx,
                                         JS_GetGlobalObject(ccx), &dest);
        }
        break;
        case VT_DATE:
        {
            // Convert date to string and frees it when we're done
            _bstr_t str(src);
            dest = StringToJSVal(ccx, str, str.length());
        }
        break;
        case VT_EMPTY:
        {
            dest = JSVAL_VOID;
        }
        break;
        case VT_NULL:
        {
            dest = JSVAL_NULL;
        }
        break;
        case VT_ERROR:
        {
            return JS_NewNumberValue(ccx, VALUE(scode), &dest);
        }
        break;
        case VT_CY:
        {
            return JS_NewNumberValue(
                ccx, 
                NS_STATIC_CAST(double,
                               isPtr ? src.pcyVal->int64 : 
                                       src.cyVal.int64) / 100.0,
                &dest);
        }
        break;
        case VT_UNKNOWN:
        default:
        {
            // Last ditch effort to convert to string
            if(FAILED(VariantChangeType(NS_CONST_CAST(VARIANT*,&src), 
                                         NS_CONST_CAST(VARIANT*,&src), 
                                         VARIANT_ALPHABOOL, VT_BSTR)))
            {
                err = NS_ERROR_XPC_BAD_CONVERT_JS;
                return JS_FALSE;
            }
            isPtr = FALSE;
        } // Fall through on success
        case VT_BSTR:
        {
            dest = StringToJSVal(ccx, VALUE(bstrVal), SysStringLen(VALUE(bstrVal)));
        }
        break;
    }
    return JS_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool XPCDispConvert::JSArrayToCOMArray ( XPCCallContext ccx,
JSObject obj,
VARIANT &  var,
nsresult err 
) [static, private]

Converts a JS Array to a safe array.

Parameters:
ccxXPConnect call context
objJSObject that is the array
varthe variant to receive the array
errreceives the error code if any of a failed conversion
Returns:
True if the conversion succeeded

Definition at line 84 of file XPCDispConvert.cpp.

{
    err = NS_OK;
    jsuint len;
    if(!JS_GetArrayLength(ccx, obj, &len))
    {
        // TODO: I think we should create a specific error for this
        err = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
        return PR_FALSE;
    }
    // Create the safe array of variants and populate it
    SAFEARRAY * array = nsnull;
    VARIANT* varArray = 0;
    for(jsuint index = 0; index < len; ++index)
    {
        jsval val;
        if(JS_GetElement(ccx, obj, index, &val))
        {
            if(!JSVAL_IS_VOID(val))
            {
                if(!array)
                {
                    // Create an array that starts at index, and has len 
                    // elements
                    array = SafeArrayCreateVector(VT_VARIANT, index, len - index);
                    if(!array)
                    {
                        err = NS_ERROR_OUT_OF_MEMORY;
                        return JS_FALSE;
                    }
                    if(FAILED(SafeArrayAccessData(array, NS_REINTERPRET_CAST(void**,&varArray))))
                    {
                        err = NS_ERROR_FAILURE;
                        return JS_FALSE;
                    }
                }
                if(!JSToCOM(ccx, val, *varArray, err))
                {
                    SafeArrayUnaccessData(array);
                    err = NS_ERROR_FAILURE;
                    // This cleans up the elements as well
                    SafeArrayDestroyData(array);
                    return JS_FALSE;
                }
            }
            if(varArray)
                ++varArray;
        }
    }
    SafeArrayUnaccessData(array);
    var.vt = VT_ARRAY | VT_VARIANT;
    var.parray = array;
    return JS_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool XPCDispConvert::JSToCOM ( XPCCallContext ccx,
jsval  src,
VARIANT &  dest,
nsresult err,
JSBool  isByRef = JS_FALSE 
) [static]

Converts a JSVal to a COM variant.

Parameters:
ccxXPConnect call context
srcJS Value to convert
destCOM variant to receive the converted value
errreceives the error code if any of a failed conversion
Returns:
True if the conversion succeeded

Definition at line 262 of file XPCDispConvert.cpp.

{
    err = NS_OK;
    VARIANT byRefVariant;
    VARIANT * varDest = isByRef ? &byRefVariant : &dest;
    varDest->vt = JSTypeToCOMType(ccx, src);
    switch (varDest->vt)
    {
        case VT_BSTR:
        {
            JSString* str = JSVAL_TO_STRING(src);
            jschar * chars = JS_GetStringChars(str);
            if(!chars)
            {
                err = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
                // Avoid cleaning up garbage
                varDest->vt = VT_EMPTY;
                return JS_FALSE;
            }

            CComBSTR val(JS_GetStringLength(str),
                         NS_REINTERPRET_CAST(const WCHAR *, chars));
            varDest->bstrVal = val.Detach();
        }
        break;
        case VT_I4:
        {
            varDest->vt = VT_I4;
            varDest->lVal = JSVAL_TO_INT(src);
        }
        break;
        case VT_R8:
        {
            varDest->vt = VT_R8;
            varDest->dblVal = *JSVAL_TO_DOUBLE(src);
        }
        break;
        case VT_EMPTY:
        case VT_NULL:
        break;
        case VT_ARRAY | VT_VARIANT:
        {
            JSObject * obj = JSVAL_TO_OBJECT(src);
            return JSArrayToCOMArray(ccx, obj, *varDest, err);
        }
        break;
        case VT_DISPATCH:
        {
            JSObject * obj = JSVAL_TO_OBJECT(src);
            IUnknown * pUnknown = nsnull;
            if(!XPCConvert::JSObject2NativeInterface(
                ccx, 
                (void**)&pUnknown, 
                obj, 
                &NSID_IDISPATCH,
                nsnull, 
                &err))
            {
                // Avoid cleaning up garbage
                varDest->vt = VT_EMPTY;
                return JS_FALSE;
            }
            varDest->vt = VT_DISPATCH;
            pUnknown->QueryInterface(IID_IDispatch, 
                                     NS_REINTERPRET_CAST(void**,
                                                         &varDest->pdispVal));
            NS_IF_RELEASE(pUnknown);
        }
        break;
        case VT_BOOL:
        {
            varDest->boolVal = JSVAL_TO_BOOLEAN(src) ? VARIANT_TRUE : VARIANT_FALSE;
        }
        break;
        default:
        {
            NS_ERROR("This is out of synce with XPCDispConvert::JSTypeToCOMType");
            err = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
            // Avoid cleaning up garbage
            varDest->vt = VT_EMPTY;
            return JS_FALSE;
        }
        break;
    }
    if(isByRef)
    {
        if(!xpc_CopyVariantByRef(byRefVariant, dest))
        {
            // Avoid cleaning up garbage
            dest.vt = VT_EMPTY;
        }
    }
    return JS_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

VARTYPE XPCDispConvert::JSTypeToCOMType ( XPCCallContext ccx,
jsval  val 
) [static]

Returns the COM type for a given jsval.

Parameters:
ccxXPConnect call context
valValue to look up the type for
Returns:
the COM variant type

Definition at line 45 of file XPCDispConvert.cpp.

{
    if(JSVAL_IS_PRIMITIVE(val))
    {
        if(JSVAL_IS_STRING(val))
        {
            return VT_BSTR;
        }
        if(JSVAL_IS_INT(val))
        {
            return VT_I4;
        }
        if(JSVAL_IS_DOUBLE(val))
        {
            return VT_R8;
        }
        if(JSVAL_IS_BOOLEAN(val))
        {
            return VT_BOOL;
        }
        if(JSVAL_IS_VOID(val))
        {
            return VT_EMPTY;
        }
        if(JSVAL_IS_NULL(val))
        {
            return VT_NULL;
        }
    }
    else
    {
        if(JS_IsArrayObject(ccx, JSVAL_TO_OBJECT(val)))
            return VT_ARRAY | VT_VARIANT;
        return VT_DISPATCH;
    }
    NS_ERROR("XPCDispConvert::JSTypeToCOMType was unable to identify the type of the jsval");
    return VT_EMPTY;
}

Here is the call graph for this function:

Here is the caller graph for this function:


The documentation for this class was generated from the following files: