members = new XPCNativeMember[totalCount]; if(!members) return nsnull;
XPCNativeInterface** inp = array; XPCNativeInterface** outp = (XPCNativeInterface**) &obj->mInterfaces; PRUint16 memberCount = 1;  *(outp++) = isup;  for(i = 0; i < count; i++) { if(isup == (cur = *(inp++))) continue; *(outp++) = cur; memberCount += cur->GetMemberCount(); } obj->mMemberCount = memberCount; obj->mInterfaceCount = slots;
XPCNativeInterface::NewInstance(XPCCallContext& ccx,                                nsIInterfaceInfo* aInfo){    static const PRUint16 MAX_LOCAL_MEMBER_COUNT = 16;    XPCNativeMember local_members[MAX_LOCAL_MEMBER_COUNT];    XPCNativeInterface* obj = nsnull;    XPCNativeMember* members = nsnull;    int i;    JSBool failed = JS_FALSE;    PRUint16 constCount;    PRUint16 methodCount;    PRUint16 totalCount;    PRUint16 realTotalCount = 0;    XPCNativeMember* cur;    JSString*  str;    jsval name;    jsval interfaceName;    // XXX Investigate lazy init? This is a problem given the    // 'placement new' scheme - we need to at least know how big to make    // the object. We might do a scan of methods to determine needed size,    // then make our object, but avoid init'ing *any* members until asked?    // Find out how often we create these objects w/o really looking at    // (or using) the members.    PRBool canScript;    if(NS_FAILED(aInfo->IsScriptable(&canScript)) || !canScript)        return nsnull;    if(NS_FAILED(aInfo->GetMethodCount(&methodCount)) ||       NS_FAILED(aInfo->GetConstantCount(&constCount)))        return nsnull;    // If the interface does not have nsISupports in its inheritance chain    // then we know we can't reflect its methods. However, some interfaces that    // are used just to reflect constants are declared this way. We need to    // go ahead and build the thing. But, we'll ignore whatever methods it may    // have.    if(!nsXPConnect::IsISupportsDescendant(aInfo))        methodCount = 0;    totalCount = methodCount + constCount;    if(totalCount > MAX_LOCAL_MEMBER_COUNT)    {        members = new XPCNativeMember[totalCount];        if(!members)            return nsnull;    }    else    {        members = local_members;    }    // NOTE: since getters and setters share a member, we might not use all    // of the member objects.    for(i = 0; i < methodCount; i++)    {        const nsXPTMethodInfo* info;        if(NS_FAILED(aInfo->GetMethodInfo(i, &info)))        {            failed = JS_TRUE;            break;        }        // don't reflect Addref or Release        if(i == 1 || i == 2)            continue;        if(!XPCConvert::IsMethodReflectable(*info))            continue;        str = JS_InternString(ccx, info->GetName());        if(!str)        {            NS_ASSERTION(0,"bad method name");            failed = JS_TRUE;            break;        }        name = STRING_TO_JSVAL(str);        if(info->IsSetter())        {            NS_ASSERTION(realTotalCount,"bad setter");            // Note: ASSUMES Getter/Setter pairs are next to each other            // This is a rule of the typelib spec.            cur = &members[realTotalCount-1];            NS_ASSERTION(cur->GetName() == name,"bad setter");            NS_ASSERTION(cur->IsReadOnlyAttribute(),"bad setter");            NS_ASSERTION(cur->GetIndex() == i-1,"bad setter");            cur->SetWritableAttribute();        }        else        {            // XXX need better way to find dups            // NS_ASSERTION(!LookupMemberByID(name),"duplicate method name");            cur = &members[realTotalCount++];            cur->SetName(name);            if(info->IsGetter())                cur->SetReadOnlyAttribute(i);            else                cur->SetMethod(i);        }    }    if(!failed)    {        for(i = 0; i < constCount; i++)        {            const nsXPTConstant* constant;            if(NS_FAILED(aInfo->GetConstant(i, &constant)))            {                failed = JS_TRUE;                break;            }            str = JS_InternString(ccx, constant->GetName());            if(!str)            {                NS_ASSERTION(0,"bad constant name");                failed = JS_TRUE;                break;            }            name = STRING_TO_JSVAL(str);            // XXX need better way to find dups            //NS_ASSERTION(!LookupMemberByID(name),"duplicate method/constant name");            cur = &members[realTotalCount++];            cur->SetName(name);            cur->SetConstant(i);        }    }    if(!failed)    {        const char* bytes;        if(NS_FAILED(aInfo->GetNameShared(&bytes)) || !bytes ||           nsnull == (str = JS_InternString(ccx, bytes)))        {            failed = JS_TRUE;        }        interfaceName = STRING_TO_JSVAL(str);    }    if(!failed)    {        // Use placement new to create an object with the right amount of space        // to hold the members array        int size = sizeof(XPCNativeInterface);        if(realTotalCount > 1)            size += (realTotalCount - 1) * sizeof(XPCNativeMember);        void* place = new char[size];        if(place)            obj = new(place) XPCNativeInterface(aInfo, interfaceName);        if(obj)        {            obj->mMemberCount = realTotalCount;            // copy valid members            if(realTotalCount)                memcpy(obj->mMembers, members,                       realTotalCount * sizeof(XPCNativeMember));        }    }    if(members && members != local_members)        delete [] members;    return obj;}