diff options
Diffstat (limited to 'js/xpconnect/src/XPCInlines.h')
-rw-r--r-- | js/xpconnect/src/XPCInlines.h | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/js/xpconnect/src/XPCInlines.h b/js/xpconnect/src/XPCInlines.h new file mode 100644 index 000000000..20c63c972 --- /dev/null +++ b/js/xpconnect/src/XPCInlines.h @@ -0,0 +1,545 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=99: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* private inline methods (#include'd by xpcprivate.h). */ + +#ifndef xpcinlines_h___ +#define xpcinlines_h___ + +#include <algorithm> + +/***************************************************************************/ + +inline void +XPCJSContext::AddVariantRoot(XPCTraceableVariant* variant) +{ + variant->AddToRootSet(&mVariantRoots); +} + +inline void +XPCJSContext::AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS) +{ + wrappedJS->AddToRootSet(&mWrappedJSRoots); +} + +inline void +XPCJSContext::AddObjectHolderRoot(XPCJSObjectHolder* holder) +{ + holder->AddToRootSet(&mObjectHolderRoots); +} + +/***************************************************************************/ + +inline bool +XPCCallContext::IsValid() const +{ + return mState != INIT_FAILED; +} + +inline XPCJSContext* +XPCCallContext::GetContext() const +{ + CHECK_STATE(HAVE_CONTEXT); + return mXPCJSContext; +} + +inline JSContext* +XPCCallContext::GetJSContext() const +{ + CHECK_STATE(HAVE_CONTEXT); + return mJSContext; +} + +inline XPCCallContext* +XPCCallContext::GetPrevCallContext() const +{ + CHECK_STATE(HAVE_CONTEXT); + return mPrevCallContext; +} + +inline nsISupports* +XPCCallContext::GetIdentityObject() const +{ + CHECK_STATE(HAVE_OBJECT); + if (mWrapper) + return mWrapper->GetIdentityObject(); + return nullptr; +} + +inline XPCWrappedNative* +XPCCallContext::GetWrapper() const +{ + if (mState == INIT_FAILED) + return nullptr; + + CHECK_STATE(HAVE_OBJECT); + return mWrapper; +} + +inline XPCWrappedNativeProto* +XPCCallContext::GetProto() const +{ + CHECK_STATE(HAVE_OBJECT); + return mWrapper ? mWrapper->GetProto() : nullptr; +} + +inline bool +XPCCallContext::CanGetTearOff() const +{ + return mState >= HAVE_OBJECT; +} + +inline XPCWrappedNativeTearOff* +XPCCallContext::GetTearOff() const +{ + CHECK_STATE(HAVE_OBJECT); + return mTearOff; +} + +inline XPCNativeScriptableInfo* +XPCCallContext::GetScriptableInfo() const +{ + CHECK_STATE(HAVE_OBJECT); + return mScriptableInfo; +} + +inline bool +XPCCallContext::CanGetSet() const +{ + return mState >= HAVE_NAME; +} + +inline XPCNativeSet* +XPCCallContext::GetSet() const +{ + CHECK_STATE(HAVE_NAME); + return mSet; +} + +inline XPCNativeInterface* +XPCCallContext::GetInterface() const +{ + CHECK_STATE(HAVE_NAME); + return mInterface; +} + +inline XPCNativeMember* +XPCCallContext::GetMember() const +{ + CHECK_STATE(HAVE_NAME); + return mMember; +} + +inline bool +XPCCallContext::HasInterfaceAndMember() const +{ + return mState >= HAVE_NAME && mInterface && mMember; +} + +inline jsid +XPCCallContext::GetName() const +{ + CHECK_STATE(HAVE_NAME); + return mName; +} + +inline bool +XPCCallContext::GetStaticMemberIsLocal() const +{ + CHECK_STATE(HAVE_NAME); + return mStaticMemberIsLocal; +} + +inline unsigned +XPCCallContext::GetArgc() const +{ + CHECK_STATE(READY_TO_CALL); + return mArgc; +} + +inline JS::Value* +XPCCallContext::GetArgv() const +{ + CHECK_STATE(READY_TO_CALL); + return mArgv; +} + +inline JS::Value* +XPCCallContext::GetRetVal() const +{ + CHECK_STATE(READY_TO_CALL); + return mRetVal; +} + +inline void +XPCCallContext::SetRetVal(const JS::Value& val) +{ + CHECK_STATE(HAVE_ARGS); + if (mRetVal) + *mRetVal = val; +} + +inline jsid +XPCCallContext::GetResolveName() const +{ + CHECK_STATE(HAVE_CONTEXT); + return XPCJSContext::Get()->GetResolveName(); +} + +inline jsid +XPCCallContext::SetResolveName(JS::HandleId name) +{ + CHECK_STATE(HAVE_CONTEXT); + return XPCJSContext::Get()->SetResolveName(name); +} + +inline XPCWrappedNative* +XPCCallContext::GetResolvingWrapper() const +{ + CHECK_STATE(HAVE_OBJECT); + return XPCJSContext::Get()->GetResolvingWrapper(); +} + +inline XPCWrappedNative* +XPCCallContext::SetResolvingWrapper(XPCWrappedNative* w) +{ + CHECK_STATE(HAVE_OBJECT); + return XPCJSContext::Get()->SetResolvingWrapper(w); +} + +inline uint16_t +XPCCallContext::GetMethodIndex() const +{ + CHECK_STATE(HAVE_OBJECT); + return mMethodIndex; +} + +inline void +XPCCallContext::SetMethodIndex(uint16_t index) +{ + CHECK_STATE(HAVE_OBJECT); + mMethodIndex = index; +} + +/***************************************************************************/ +inline XPCNativeInterface* +XPCNativeMember::GetInterface() const +{ + XPCNativeMember* arrayStart = + const_cast<XPCNativeMember*>(this - mIndexInInterface); + size_t arrayStartOffset = XPCNativeInterface::OffsetOfMembers(); + char* xpcNativeInterfaceStart = + reinterpret_cast<char*>(arrayStart) - arrayStartOffset; + return reinterpret_cast<XPCNativeInterface*>(xpcNativeInterfaceStart); +} + +/***************************************************************************/ + +inline const nsIID* +XPCNativeInterface::GetIID() const +{ + const nsIID* iid; + return NS_SUCCEEDED(mInfo->GetIIDShared(&iid)) ? iid : nullptr; +} + +inline const char* +XPCNativeInterface::GetNameString() const +{ + const char* name; + return NS_SUCCEEDED(mInfo->GetNameShared(&name)) ? name : nullptr; +} + +inline XPCNativeMember* +XPCNativeInterface::FindMember(jsid name) const +{ + const XPCNativeMember* member = mMembers; + for (int i = (int) mMemberCount; i > 0; i--, member++) + if (member->GetName() == name) + return const_cast<XPCNativeMember*>(member); + return nullptr; +} + +inline bool +XPCNativeInterface::HasAncestor(const nsIID* iid) const +{ + bool found = false; + mInfo->HasAncestor(iid, &found); + return found; +} + +/* static */ +inline size_t +XPCNativeInterface::OffsetOfMembers() +{ + return offsetof(XPCNativeInterface, mMembers); +} + +/***************************************************************************/ + +inline XPCNativeSetKey::XPCNativeSetKey(XPCNativeSet* baseSet, + XPCNativeInterface* addition) + : mBaseSet(baseSet) + , mAddition(addition) +{ + MOZ_ASSERT(mBaseSet); + MOZ_ASSERT(mAddition); + MOZ_ASSERT(!mBaseSet->HasInterface(mAddition)); +} + +/***************************************************************************/ + +inline bool +XPCNativeSet::FindMember(jsid name, XPCNativeMember** pMember, + uint16_t* pInterfaceIndex) const +{ + XPCNativeInterface* const * iface; + int count = (int) mInterfaceCount; + int i; + + // look for interface names first + + for (i = 0, iface = mInterfaces; i < count; i++, iface++) { + if (name == (*iface)->GetName()) { + if (pMember) + *pMember = nullptr; + if (pInterfaceIndex) + *pInterfaceIndex = (uint16_t) i; + return true; + } + } + + // look for method names + for (i = 0, iface = mInterfaces; i < count; i++, iface++) { + XPCNativeMember* member = (*iface)->FindMember(name); + if (member) { + if (pMember) + *pMember = member; + if (pInterfaceIndex) + *pInterfaceIndex = (uint16_t) i; + return true; + } + } + return false; +} + +inline bool +XPCNativeSet::FindMember(jsid name, XPCNativeMember** pMember, + RefPtr<XPCNativeInterface>* pInterface) const +{ + uint16_t index; + if (!FindMember(name, pMember, &index)) + return false; + *pInterface = mInterfaces[index]; + return true; +} + +inline bool +XPCNativeSet::FindMember(JS::HandleId name, + XPCNativeMember** pMember, + RefPtr<XPCNativeInterface>* pInterface, + XPCNativeSet* protoSet, + bool* pIsLocal) const +{ + XPCNativeMember* Member; + RefPtr<XPCNativeInterface> Interface; + XPCNativeMember* protoMember; + + if (!FindMember(name, &Member, &Interface)) + return false; + + *pMember = Member; + + *pIsLocal = + !Member || + !protoSet || + (protoSet != this && + !protoSet->MatchesSetUpToInterface(this, Interface) && + (!protoSet->FindMember(name, &protoMember, (uint16_t*)nullptr) || + protoMember != Member)); + + *pInterface = Interface.forget(); + + return true; +} + +inline XPCNativeInterface* +XPCNativeSet::FindNamedInterface(jsid name) const +{ + XPCNativeInterface* const * pp = mInterfaces; + + for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { + XPCNativeInterface* iface = *pp; + + if (name == iface->GetName()) + return iface; + } + return nullptr; +} + +inline XPCNativeInterface* +XPCNativeSet::FindInterfaceWithIID(const nsIID& iid) const +{ + XPCNativeInterface* const * pp = mInterfaces; + + for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { + XPCNativeInterface* iface = *pp; + + if (iface->GetIID()->Equals(iid)) + return iface; + } + return nullptr; +} + +inline bool +XPCNativeSet::HasInterface(XPCNativeInterface* aInterface) const +{ + XPCNativeInterface* const * pp = mInterfaces; + + for (int i = (int) mInterfaceCount; i > 0; i--, pp++) { + if (aInterface == *pp) + return true; + } + return false; +} + +inline bool +XPCNativeSet::HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const +{ + return HasInterfaceWithAncestor(aInterface->GetIID()); +} + +inline bool +XPCNativeSet::HasInterfaceWithAncestor(const nsIID* iid) const +{ + // We can safely skip the first interface which is *always* nsISupports. + XPCNativeInterface* const * pp = mInterfaces+1; + for (int i = (int) mInterfaceCount; i > 1; i--, pp++) + if ((*pp)->HasAncestor(iid)) + return true; + + // This is rare, so check last. + if (iid == &NS_GET_IID(nsISupports)) + return true; + + return false; +} + +inline bool +XPCNativeSet::MatchesSetUpToInterface(const XPCNativeSet* other, + XPCNativeInterface* iface) const +{ + int count = std::min(int(mInterfaceCount), int(other->mInterfaceCount)); + + XPCNativeInterface* const * pp1 = mInterfaces; + XPCNativeInterface* const * pp2 = other->mInterfaces; + + for (int i = (int) count; i > 0; i--, pp1++, pp2++) { + XPCNativeInterface* cur = (*pp1); + if (cur != (*pp2)) + return false; + if (cur == iface) + return true; + } + return false; +} + +/***************************************************************************/ + +inline +JSObject* XPCWrappedNativeTearOff::GetJSObjectPreserveColor() const +{ + return mJSObject.unbarrieredGetPtr(); +} + +inline +JSObject* XPCWrappedNativeTearOff::GetJSObject() +{ + return mJSObject; +} + +inline +void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj) +{ + MOZ_ASSERT(!IsMarked()); + mJSObject = JSObj; +} + +inline +void XPCWrappedNativeTearOff::JSObjectMoved(JSObject* obj, const JSObject* old) +{ + MOZ_ASSERT(!IsMarked()); + MOZ_ASSERT(mJSObject.unbarrieredGetPtr() == old); + mJSObject = obj; +} + +inline +XPCWrappedNativeTearOff::~XPCWrappedNativeTearOff() +{ + MOZ_COUNT_DTOR(XPCWrappedNativeTearOff); + MOZ_ASSERT(!(GetInterface() || GetNative() || GetJSObjectPreserveColor()), + "tearoff not empty in dtor"); +} + +/***************************************************************************/ + +inline bool +XPCWrappedNative::HasInterfaceNoQI(const nsIID& iid) +{ + return nullptr != GetSet()->FindInterfaceWithIID(iid); +} + +inline void +XPCWrappedNative::SweepTearOffs() +{ + for (XPCWrappedNativeTearOff* to = &mFirstTearOff; to; to = to->GetNextTearOff()) { + bool marked = to->IsMarked(); + to->Unmark(); + if (marked) + continue; + + // If this tearoff does not have a live dedicated JSObject, + // then let's recycle it. + if (!to->GetJSObjectPreserveColor()) { + to->SetNative(nullptr); + to->SetInterface(nullptr); + } + } +} + +/***************************************************************************/ + +inline bool +xpc_ForcePropertyResolve(JSContext* cx, JS::HandleObject obj, jsid idArg) +{ + JS::RootedId id(cx, idArg); + bool dummy; + return JS_HasPropertyById(cx, obj, id, &dummy); +} + +inline jsid +GetJSIDByIndex(JSContext* cx, unsigned index) +{ + XPCJSContext* xpcx = nsXPConnect::XPConnect()->GetContext(); + return xpcx->GetStringID(index); +} + +inline +bool ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx) +{ + XPCThrower::ThrowBadParam(rv, paramNum, ccx); + return false; +} + +inline +void ThrowBadResult(nsresult result, XPCCallContext& ccx) +{ + XPCThrower::ThrowBadResult(NS_ERROR_XPC_NATIVE_RETURNED_FAILURE, + result, ccx); +} + +/***************************************************************************/ + +#endif /* xpcinlines_h___ */ |