diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 86cbf61ca646..6f20f0cccad6 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -4030,7 +4030,7 @@ public: * @param errorReporter the error reporter callback function to set */ - void StartEvaluating(JSErrorReporter errorReporter = nsnull); + PRBool StartEvaluating(JSObject *scope, JSErrorReporter errorReporter = nsnull); /** * Does the post script evaluation and resets the error reporter */ @@ -4041,6 +4041,7 @@ private: PRBool mErrorReporterSet; PRBool mEvaluated; jsword mContextHasThread; + JSAutoEnterCompartment mEnterCompartment; MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER // No copying or assignment allowed diff --git a/js/src/xpconnect/src/xpcwrappedjsclass.cpp b/js/src/xpconnect/src/xpcwrappedjsclass.cpp index 8e8736d8975b..1626f027e2b1 100644 --- a/js/src/xpconnect/src/xpcwrappedjsclass.cpp +++ b/js/src/xpconnect/src/xpcwrappedjsclass.cpp @@ -54,12 +54,13 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass) // the value of this variable is never used - we use its address as a sentinel static uint32 zero_methods_descriptor; -void AutoScriptEvaluate::StartEvaluating(JSErrorReporter errorReporter) +PRBool AutoScriptEvaluate::StartEvaluating(JSObject *scope, JSErrorReporter errorReporter) { NS_PRECONDITION(!mEvaluated, "AutoScriptEvaluate::Evaluate should only be called once"); - if(!mJSContext) - return; + if (!mJSContext) + return PR_TRUE; + mEvaluated = PR_TRUE; if(!mJSContext->errorReporter) { @@ -70,6 +71,9 @@ void AutoScriptEvaluate::StartEvaluating(JSErrorReporter errorReporter) if (mContextHasThread) JS_BeginRequest(mJSContext); + if (!mEnterCompartment.enter(mJSContext, scope)) + return PR_FALSE; + // Saving the exception state keeps us from interfering with another script // that may also be running on this context. This occurred first with the // js debugger, as described in @@ -85,6 +89,8 @@ void AutoScriptEvaluate::StartEvaluating(JSErrorReporter errorReporter) mState = JS_SaveExceptionState(mJSContext); JS_ClearPendingException(mJSContext); } + + return PR_TRUE; } AutoScriptEvaluate::~AutoScriptEvaluate() @@ -250,10 +256,6 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(XPCCallContext& ccx, JSBool success = JS_FALSE; jsid funid; jsval fun; - JSAutoEnterCompartment ac; - - if(!ac.enter(cx, jsobj)) - return nsnull; // Don't call the actual function on a content object. We'll determine // whether or not a content object is capable of implementing the @@ -265,6 +267,14 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(XPCCallContext& ccx, return nsnull; } + // OK, it looks like we'll be calling into JS code. + AutoScriptEvaluate scriptEval(cx); + + // XXX we should install an error reporter that will send reports to + // the JS error console service. + if (!scriptEval.StartEvaluating(jsobj)) + return nsnull; + // check upfront for the existence of the function property funid = mRuntime->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE); if(!JS_GetPropertyById(cx, jsobj, funid, &fun) || JSVAL_IS_PRIMITIVE(fun)) @@ -290,14 +300,6 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(XPCCallContext& ccx, return nsnull; } - // OK, it looks like we'll be calling into JS code. - - AutoScriptEvaluate scriptEval(cx); - - // XXX we should install an error reporter that will send reports to - // the JS error console service. - scriptEval.StartEvaluating(); - id = xpc_NewIDObject(cx, jsobj, aIID); if(id) { @@ -402,7 +404,8 @@ nsXPCWrappedJSClass::GetNamedPropertyAsVariant(XPCCallContext& ccx, nsresult rv = NS_ERROR_FAILURE; AutoScriptEvaluate scriptEval(cx); - scriptEval.StartEvaluating(); + if (!scriptEval.StartEvaluating(aJSObj)) + return NS_ERROR_FAILURE; ok = JS_ValueToId(cx, aName, &id) && GetNamedPropertyAsVariantRaw(ccx, aJSObj, id, aResult, &rv); @@ -425,7 +428,8 @@ nsXPCWrappedJSClass::BuildPropertyEnumerator(XPCCallContext& ccx, // Saved state must be restored, all exits through 'out'... AutoScriptEvaluate scriptEval(cx); - scriptEval.StartEvaluating(); + if (!scriptEval.StartEvaluating(aJSObj)) + return NS_ERROR_FAILURE; idArray = JS_Enumerate(cx, aJSObj); if(!idArray) @@ -1306,16 +1310,11 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, } js::AutoValueVector args(cx); - /* This must come before AutoScriptEvaluate */ - JSAutoEnterCompartment ac; AutoScriptEvaluate scriptEval(cx); ContextPrincipalGuard principalGuard(ccx); obj = thisObj = wrapper->GetJSObject(); - if (!ac.enter(ccx, obj)) - goto pre_call_clean_up; - // XXX ASSUMES that retval is last arg. The xpidl compiler ensures this. paramCount = info->num_args; argc = paramCount - @@ -1324,7 +1323,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, if(!cx || !xpcc || !IsReflectable(methodIndex)) goto pre_call_clean_up; - scriptEval.StartEvaluating(xpcWrappedJSErrorReporter); + if (!scriptEval.StartEvaluating(obj, xpcWrappedJSErrorReporter)) + goto pre_call_clean_up; xpcc->SetPendingResult(pending_result); xpcc->SetException(nsnull);