bug 80062. Various post xpcdom branch landing fixes. r=dbradley sr=jst

git-svn-id: svn://10.0.0.236/trunk@94729 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
jband%netscape.com
2001-05-12 02:56:47 +00:00
parent 9fdb886692
commit a537ae5c5c
14 changed files with 165 additions and 135 deletions

View File

@@ -545,6 +545,11 @@ interface nsIXPConnect : nsISupports
in nsISupports aCOMObj);
void clearAllWrappedNativeSecurityPolicies();
nsIXPConnectJSObjectHolder
getWrappedNativePrototype(in JSContextPtr aJSContext,
in JSObjectPtr aScope,
in nsIClassInfo aClassInfo);
};

View File

@@ -18,10 +18,6 @@
- VERIFY only share protos if scriptable flag says so.
- FOORPRINT & PERFORMANCE
? look into optional hashtable in interface sets
FWIW, I'm thinking this is likely to not be a real win (and will
certainly have a cost).
The JS engine caches the bulk of such lookups for us anyway.
- CODE MAINTAINABILITY
- more code comments
@@ -38,7 +34,6 @@
- add multi-threaded tests
- DOCS
- update typelib spec ([astring] and [function])
- xpconnect api docs
- discussion of flattening and implications
- add to the faqs

View File

@@ -855,6 +855,41 @@ nsXPConnect::ClearAllWrappedNativeSecurityPolicies()
return XPCWrappedNativeScope::ClearAllWrappedNativeSecurityPolicies(ccx);
}
/* nsIXPConnectJSObjectHolder getWrappedNativePrototype (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsIClassInfo aClassInfo); */
NS_IMETHODIMP
nsXPConnect::GetWrappedNativePrototype(JSContext * aJSContext,
JSObject * aScope,
nsIClassInfo *aClassInfo,
nsIXPConnectJSObjectHolder **_retval)
{
XPCCallContext ccx(NATIVE_CALLER, aJSContext);
if(!ccx.IsValid())
return UnexpectedFailure(NS_ERROR_FAILURE);
XPCWrappedNativeScope* scope =
XPCWrappedNativeScope::FindInJSObjectScope(ccx, aScope);
if(!scope)
return UnexpectedFailure(NS_ERROR_FAILURE);
XPCNativeScriptableCreateInfo sciProto;
XPCWrappedNative::GatherProtoScriptableCreateInfo(aClassInfo, &sciProto);
XPCWrappedNativeProto* proto =
XPCWrappedNativeProto::GetNewOrUsed(ccx, scope, aClassInfo,
&sciProto, JS_FALSE);
if(!proto)
return UnexpectedFailure(NS_ERROR_FAILURE);
nsIXPConnectJSObjectHolder* holder;
*_retval = holder = XPCJSObjectHolder::newHolder(ccx,
proto->GetJSProtoObject());
if(!holder)
return UnexpectedFailure(NS_ERROR_FAILURE);
NS_ADDREF(holder);
return NS_OK;
}
/* void debugDump (in short depth); */
NS_IMETHODIMP
nsXPConnect::DebugDump(PRInt16 depth)

View File

@@ -236,26 +236,28 @@ XPCCallContext::SetArgsAndResultPtr(uintN argc,
mState = HAVE_ARGS;
}
JSBool
nsresult
XPCCallContext::CanCallNow()
{
nsresult rv;
if(!HasInterfaceAndMember())
return JS_FALSE;
return NS_ERROR_UNEXPECTED;
if(mState < HAVE_ARGS)
return JS_FALSE;
return NS_ERROR_UNEXPECTED;
if(!mTearOff)
mTearOff = mWrapper->FindTearOff(*this, mInterface);
if(mTearOff)
{
// Refresh in case FindTearOff extended the set
mSet = mWrapper->GetSet();
mState = READY_TO_CALL;
return JS_TRUE;
mTearOff = mWrapper->FindTearOff(*this, mInterface, JS_FALSE, &rv);
if(!mTearOff)
return NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED;
}
return JS_FALSE;
// Refresh in case FindTearOff extended the set
mSet = mWrapper->GetSet();
mState = READY_TO_CALL;
return NS_OK;
}
void

View File

@@ -975,7 +975,7 @@ XPCConvert::ConstructException(nsresult rv, const char* message,
nsISupports* data,
nsIException** exceptn)
{
static const char format[] = "%s [%s::%s]";
static const char format[] = "\'%s\' when calling method: [%s::%s]";
const char * msg = message;
char* sz = nsnull;

View File

@@ -136,8 +136,8 @@ nsXPCException::nsXPCException()
mLocation(nsnull),
mData(nsnull),
mFilename(nsnull),
mColumnNumber(0),
mLineNumber(0),
mColumnNumber(0),
mInner(nsnull),
mInitialized(PR_FALSE)
{

View File

@@ -51,7 +51,6 @@ const char* XPCJSRuntime::mStrings[] = {
"wrappedJSObject", // IDX_WRAPPED_JSOBJECT
"Object", // IDX_OBJECT
"prototype", // IDX_PROTOTYPE
"__callableinfo", // IDX_CALLABLE_INFO_PROP_NAME
"createInstance" // IDX_CREATE_INSTANCE
};

View File

@@ -85,7 +85,9 @@ HashNativeKey(JSDHashTable *table, const void *key)
if(!Set)
{
NS_ASSERTION(Addition, "bad key");
h ^= (JSHashNumber) Addition;
// This would be an XOR like below.
// But "0 ^ x == x". So it does not matter.
h = (JSHashNumber) Addition >> 2;
}
else
{
@@ -97,15 +99,15 @@ HashNativeKey(JSDHashTable *table, const void *key)
for(PRUint16 i = 0; i < count; i++)
{
if(i == Position)
h ^= (JSHashNumber) Addition;
h ^= (JSHashNumber) Addition >> 2;
else
h ^= (JSHashNumber) *(Current++);
h ^= (JSHashNumber) *(Current++) >> 2;
}
}
else
{
for(PRUint16 i = 0; i < count; i++)
h ^= (JSHashNumber) *(Current++);
h ^= (JSHashNumber) *(Current++) >> 2;
}
}

View File

@@ -124,29 +124,20 @@
#ifdef DEBUG
#define XPC_DETECT_LEADING_UPPERCASE_ACCESS_ERRORS
#endif
#ifdef DEBUG
#define XPC_REPORT_SHADOWED_WRAPPED_NATIVE_MEMBERS
#endif
#ifdef DEBUG
#define XPC_CHECK_WRAPPER_THREADSAFETY
#endif
#if defined(DEBUG_xpc_hacker)
#define XPC_CHECK_CLASSINFO_CLAIMS
#if defined(DEBUG_jst)
#define XPC_ASSERT_CLASSINFO_CLAIMS
#endif
#endif
#if defined(DEBUG_xpc_hacker)
#define XPC_DUMP_AT_SHUTDOWN
#define XPC_TRACK_WRAPPER_STATS
#define XPC_TRACK_SCOPE_STATS
#define XPC_TRACK_PROTO_STATS
#define XPC_CHECK_WRAPPERS_AT_SHUTDOWN
#define XPC_REPORT_SHADOWED_WRAPPED_NATIVE_MEMBERS
#define XPC_CHECK_CLASSINFO_CLAIMS
#if defined(DEBUG_jst)
#define XPC_ASSERT_CLASSINFO_CLAIMS
#endif
//#define DEBUG_stats_jband 1
//#define XPC_REPORT_NATIVE_INTERFACE_AND_SET_FLUSHING
//#define XPC_REPORT_JSCLASS_FLUSHING
@@ -499,7 +490,6 @@ public:
IDX_WRAPPED_JSOBJECT ,
IDX_OBJECT ,
IDX_PROTOTYPE ,
IDX_CALLABLE_INFO_PROP_NAME ,
IDX_CREATE_INSTANCE ,
IDX_TOTAL_COUNT // just a count of the above
};
@@ -760,7 +750,7 @@ public:
void SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member,
JSBool isSetter);
JSBool CanCallNow();
nsresult CanCallNow();
void SystemIsBeingShutDown();
@@ -1372,7 +1362,7 @@ public:
void
GetScriptableShared(XPCNativeScriptableShared* shared) {mShared = shared;}
private:
protected:
XPCNativeScriptableInfo(nsIXPCScriptable* scriptable = nsnull,
XPCNativeScriptableShared* shared = nsnull)
: mCallback(scriptable), mShared(shared)
@@ -1775,6 +1765,10 @@ public:
char* ToString(XPCCallContext& ccx,
XPCWrappedNativeTearOff* to = nsnull) const;
static nsresult GatherProtoScriptableCreateInfo(
nsIClassInfo* classInfo,
XPCNativeScriptableCreateInfo* sciProto);
// Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
protected:
XPCWrappedNative(); // not implemented
@@ -1804,7 +1798,7 @@ private:
JSBool InitTearOffJSObject(XPCCallContext& ccx,
XPCWrappedNativeTearOff* to);
static nsresult GatherScriptableInfo(
static nsresult GatherScriptableCreateInfo(
nsISupports* obj,
nsIClassInfo* classInfo,
XPCNativeScriptableCreateInfo* sciProto,
@@ -2013,8 +2007,6 @@ private:
/***************************************************************************/
#ifdef XPC_OLD_DOM_SUPPORT
class XPCJSObjectHolder : public nsIXPConnectJSObjectHolder
{
public:
@@ -2037,8 +2029,6 @@ private:
JSObject* mJSObj;
};
#endif
/***************************************************************************
****************************************************************************
*

View File

@@ -124,38 +124,36 @@ XPCJSContextStack::GetSafeJSContext(JSContext * *aSafeJSContext)
if(!mSafeJSContext)
{
JSRuntime *rt;
nsCOMPtr<nsIJSRuntimeService> rtsvc =
do_GetService(XPC_RUNTIME_CONTRACTID);
if(rtsvc && NS_SUCCEEDED(rtsvc->GetRuntime(&rt)) && rt)
XPCJSRuntime* xpcrt;
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
nsCOMPtr<nsIXPConnect> xpcholder(NS_STATIC_CAST(nsIXPConnect*, xpc));
if(xpc && (xpcrt = xpc->GetRuntime()) && (rt = xpcrt->GetJSRuntime()))
{
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
if(xpc)
mSafeJSContext = JS_NewContext(rt, 8192);
if(mSafeJSContext)
{
mSafeJSContext = JS_NewContext(rt, 8192);
if(mSafeJSContext)
// scoped JS Request
AutoJSRequestWithNoCallContext req(mSafeJSContext);
JSObject *glob;
glob = JS_NewObject(mSafeJSContext, &global_class, NULL, NULL);
if(!glob || NS_FAILED(xpc->InitClasses(mSafeJSContext, glob)))
{
// scoped JS Request
AutoJSRequestWithNoCallContext req(mSafeJSContext);
JSObject *glob;
glob = JS_NewObject(mSafeJSContext, &global_class, NULL, NULL);
if(!glob ||
NS_FAILED(xpc->InitClasses(mSafeJSContext, glob)))
{
// Explicitly end the request since we are about to kill
// the JSContext that 'req' will try to use when it
// goes out of scope.
req.EndRequest();
JS_DestroyContext(mSafeJSContext);
mSafeJSContext = nsnull;
}
// Save it off so we can destroy it later, even if
// mSafeJSContext has been set to another context
// via SetSafeJSContext. If we don't get here,
// then mSafeJSContext must have been set via
// SetSafeJSContext, and we're not responsible for
// destroying the passed-in context.
mOwnSafeJSContext = mSafeJSContext;
// Explicitly end the request since we are about to kill
// the JSContext that 'req' will try to use when it
// goes out of scope.
req.EndRequest();
JS_DestroyContext(mSafeJSContext);
mSafeJSContext = nsnull;
}
// Save it off so we can destroy it later, even if
// mSafeJSContext has been set to another context
// via SetSafeJSContext. If we don't get here,
// then mSafeJSContext must have been set via
// SetSafeJSContext, and we're not responsible for
// destroying the passed-in context.
mOwnSafeJSContext = mSafeJSContext;
}
}
}

View File

@@ -447,7 +447,7 @@ nsXPCWrappedJSClass::GetArraySizeFromParam(JSContext* cx,
const nsXPTParamInfo& arg_param = method->GetParam(argnum);
const nsXPTType& arg_type = arg_param.GetType();
// XXX require PRUint32 here - need to require in compiler too!
// The xpidl compiler ensures this. We reaffirm it for safety.
if(arg_type.IsPointer() || arg_type.TagPart() != nsXPTType::T_U32)
return JS_FALSE;
@@ -606,7 +606,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
obj = thisObj = wrapper->GetJSObject();
// XXX ASSUMES that retval is last arg.
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
paramCount = info->GetParamCount();
argc = paramCount -
(paramCount && info->GetParam(paramCount-1).IsRetval() ? 1 : 0);

View File

@@ -63,8 +63,8 @@ static int DEBUG_WrappedNativeTotalCalls;
static int DEBUG_WrappedNativeMethodCalls;
static int DEBUG_WrappedNativeGetterCalls;
static int DEBUG_WrappedNativeSetterCalls;
#define DEBUG_CHUCKS_TO_COUNT 4
static int DEBUG_WrappedNativeTearOffChunkCounts[DEBUG_CHUCKS_TO_COUNT+1];
#define DEBUG_CHUNKS_TO_COUNT 4
static int DEBUG_WrappedNativeTearOffChunkCounts[DEBUG_CHUNKS_TO_COUNT+1];
static PRBool DEBUG_DumpedWrapperStats;
#endif
@@ -112,8 +112,8 @@ static void DEBUG_TrackDeleteWrapper(XPCWrappedNative* wrapper)
DEBUG_LiveWrappedNativeNoProtoCount--;
int extraChunkCount = wrapper->DEBUG_CountOfTearoffChunks() - 1;
if(extraChunkCount > DEBUG_CHUCKS_TO_COUNT)
extraChunkCount = DEBUG_CHUCKS_TO_COUNT;
if(extraChunkCount > DEBUG_CHUNKS_TO_COUNT)
extraChunkCount = DEBUG_CHUNKS_TO_COUNT;
DEBUG_WrappedNativeTearOffChunkCounts[extraChunkCount]++;
#endif
}
@@ -173,7 +173,7 @@ static void DEBUG_TrackShutdownWrapper(XPCWrappedNative* wrapper)
printf("(wrappers / tearoffs): (");
int i;
for(i = 0; i < DEBUG_CHUCKS_TO_COUNT; i++)
for(i = 0; i < DEBUG_CHUNKS_TO_COUNT; i++)
{
printf("%d / %d, ",
DEBUG_WrappedNativeTearOffChunkCounts[i],
@@ -251,9 +251,9 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
XPCNativeScriptableCreateInfo sciProto;
XPCNativeScriptableCreateInfo sciWrapper;
if(NS_FAILED(GatherScriptableInfo(identity,
isClassInfo ? nsnull : info.get(),
&sciProto, &sciWrapper)))
if(NS_FAILED(GatherScriptableCreateInfo(identity,
isClassInfo ? nsnull : info.get(),
&sciProto, &sciWrapper)))
return NS_ERROR_FAILURE;
JSObject* parent = Scope->GetGlobalJSObject();
@@ -495,50 +495,63 @@ XPCWrappedNative::~XPCWrappedNative()
NS_IF_RELEASE(mIdentity);
}
// This is factored out so that it can be called publicly
// static
nsresult
XPCWrappedNative::GatherProtoScriptableCreateInfo(
nsIClassInfo* classInfo,
XPCNativeScriptableCreateInfo* sciProto)
{
NS_ASSERTION(classInfo, "bad param");
NS_ASSERTION(sciProto && !sciProto->GetCallback(), "bad param");
nsCOMPtr<nsISupports> possibleHelper;
nsresult rv = classInfo->GetHelperForLanguage(
nsIProgrammingLanguage::JAVASCRIPT,
getter_AddRefs(possibleHelper));
if(NS_SUCCEEDED(rv) && possibleHelper)
{
nsCOMPtr<nsIXPCScriptable> helper(do_QueryInterface(possibleHelper));
if(helper)
{
JSUint32 flags;
rv = helper->GetScriptableFlags(&flags);
if(NS_FAILED(rv))
flags = 0;
sciProto->SetCallback(helper);
sciProto->SetFlags(flags);
}
}
return NS_OK;
}
// static
nsresult
XPCWrappedNative::GatherScriptableInfo(
XPCWrappedNative::GatherScriptableCreateInfo(
nsISupports* obj,
nsIClassInfo* classInfo,
XPCNativeScriptableCreateInfo* sciProto,
XPCNativeScriptableCreateInfo* sciWrapper)
{
nsCOMPtr<nsIXPCScriptable> helper;
NS_ASSERTION(sciProto && !sciProto->GetCallback(), "bad param");
NS_ASSERTION(sciWrapper && !sciWrapper->GetCallback(), "bad param");
// Get the class scriptable helper (if present)
if(classInfo)
{
nsCOMPtr<nsISupports> possibleHelper;
nsresult rv = classInfo->GetHelperForLanguage(
nsIProgrammingLanguage::JAVASCRIPT,
getter_AddRefs(possibleHelper));
if(NS_SUCCEEDED(rv) && possibleHelper)
{
helper = do_QueryInterface(possibleHelper);
if(helper)
{
JSUint32 flags;
rv = helper->GetScriptableFlags(&flags);
if(NS_FAILED(rv))
flags = 0;
GatherProtoScriptableCreateInfo(classInfo, sciProto);
sciProto->SetCallback(helper);
sciProto->SetFlags(flags);
sciWrapper->SetCallback(sciProto->GetCallback());
sciWrapper->SetFlags(sciProto->GetFlags());
sciWrapper->SetCallback(helper);
sciWrapper->SetFlags(flags);
if(sciProto->GetFlags().DontAskInstanceForScriptable())
return NS_OK;
}
}
if(sciProto->GetFlags().DontAskInstanceForScriptable())
return NS_OK;
}
// Do the same for the wrapper specific scriptable
helper = do_QueryInterface(obj);
nsCOMPtr<nsIXPCScriptable> helper(do_QueryInterface(obj));
if(helper)
{
JSUint32 flags;
@@ -817,6 +830,7 @@ XPCWrappedNative::FlatJSObjectFinalized(JSContext *cx, JSObject *obj)
JSObject* jso = to->GetJSObject();
if(jso)
{
NS_ASSERTION(JS_IsAboutToBeFinalized(cx, jso), "bad!");
JS_SetPrivate(cx, jso, nsnull);
to->JSObjectFinalized();
}
@@ -966,6 +980,7 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
newProto->GetJSProtoObject()))
{
// this is bad, very bad
NS_ERROR("JS_SetPrototype failed");
NS_RELEASE(wrapper);
return NS_ERROR_FAILURE;
}
@@ -1210,7 +1225,6 @@ XPCWrappedNative::InitTearOff(XPCCallContext& ccx,
// Determine if the object really does this interface...
nsresult rv = NS_OK;
const nsIID* iid = aInterface->GetIID();
nsISupports* identity = GetIdentityObject();
nsISupports* obj;
@@ -1359,7 +1373,7 @@ GetArraySizeFromParam(XPCCallContext& ccx,
const nsXPTParamInfo& arg_param = methodInfo->GetParam(argnum);
const nsXPTType& arg_type = arg_param.GetType();
// XXX require PRUint32 here - need to require in compiler too!
// The xpidl compiler ensures this. We reaffirm it for safety.
if(arg_type.IsPointer() || arg_type.TagPart() != nsXPTType::T_U32)
return Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, ccx);
@@ -1400,7 +1414,8 @@ GetInterfaceTypeFromParam(XPCCallContext& ccx,
const nsXPTParamInfo& arg_param = methodInfo->GetParam(argnum);
const nsXPTType& arg_type = arg_param.GetType();
// XXX require iid type here - need to require in compiler too!
// The xpidl compiler ensures this. We reaffirm it for safety.
if(!arg_type.IsPointer() || arg_type.TagPart() != nsXPTType::T_IID)
return ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO, paramIndex, ccx);
@@ -1418,10 +1433,15 @@ JSBool
XPCWrappedNative::CallMethod(XPCCallContext& ccx,
CallMode mode /*= CALL_METHOD */)
{
if(!ccx.CanCallNow())
nsresult rv = ccx.CanCallNow();
if(NS_FAILED(rv))
{
NS_ASSERTION(0, "hmm? We are finding out about this late!");
return Throw(NS_ERROR_XPC_UNEXPECTED, ccx);
// If the security manager is complaining then this is not really an
// internal error in xpconnect. So, no reason to botch the assertion.
NS_ASSERTION(rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO,
"hmm? CanCallNow failed in XPCWrappedNative::CallMethod. "
"We are finding out about this late!");
return Throw(rv, ccx);
}
DEBUG_TrackWrapperCall(ccx.GetWrapper(), mode);
@@ -1510,7 +1530,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx,
goto done;
}
// XXX ASSUMES that retval is last arg.
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
paramCount = methodInfo->GetParamCount();
requiredArgs = paramCount;
if(paramCount && methodInfo->GetParam(paramCount-1).IsRetval())
@@ -2112,7 +2132,7 @@ NS_IMETHODIMP XPCWrappedNative::DebugDump(PRInt16 depth)
{
XPC_LOG_INDENT();
XPC_LOG_ALWAYS(("mScriptable @ %x", mScriptableInfo->GetCallback()));
XPC_LOG_ALWAYS(("mFlags of %x", mScriptableInfo->GetFlags()));
XPC_LOG_ALWAYS(("mFlags of %x", (PRUint32)mScriptableInfo->GetFlags()));
XPC_LOG_ALWAYS(("mJSClass @ %x", mScriptableInfo->GetJSClass()));
XPC_LOG_OUTDENT();
}
@@ -2696,12 +2716,6 @@ void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper)
}
#endif
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
#ifdef XPC_OLD_DOM_SUPPORT
NS_IMPL_THREADSAFE_ISUPPORTS1(XPCJSObjectHolder, nsIXPConnectJSObjectHolder)
NS_IMETHODIMP
@@ -2735,5 +2749,3 @@ XPCJSObjectHolder::newHolder(JSContext* cx, JSObject* obj)
}
return new XPCJSObjectHolder(cx, obj);
}
#endif

View File

@@ -483,14 +483,6 @@ XPC_WN_OnlyIWrite_PropertyStub(JSContext *cx, JSObject *obj, jsval idval, jsval
if(ccx.GetResolveName() == idval)
return JS_TRUE;
// No, we use shared setters, so this should not matter
// (modulo the engine resolve bugs brendan is helping with!)
/*
if(ccx.GetInterface() && ccx.GetMember() &&
ccx.GetMember()->IsWritableAttribute())
return JS_TRUE;
*/
return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
}

View File

@@ -234,7 +234,7 @@ XPCWrappedNativeProto::DebugDump(PRInt16 depth)
{
XPC_LOG_INDENT();
XPC_LOG_ALWAYS(("mScriptable @ %x", mScriptableInfo->GetCallback()));
XPC_LOG_ALWAYS(("mFlags of %x", mScriptableInfo->GetFlags()));
XPC_LOG_ALWAYS(("mFlags of %x", (PRUint32)mScriptableInfo->GetFlags()));
XPC_LOG_ALWAYS(("mJSClass @ %x", mScriptableInfo->GetJSClass()));
XPC_LOG_OUTDENT();
}