Bug 672893 - Don't #include jscompartment.h in xpconnect. r=cdleary.
authorJason Orendorff <jorendorff@mozilla.com>
Sat, 06 Aug 2011 16:05:25 -0500
changeset 76489 3326454d70f5116055e1f32df8d733524c3ff04a
parent 76484 5b34c14d9f842c1357abe0882cc61ffa8a2de7b5
child 76490 502c33ae0d8115e64f5f661409c371b372debf10
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewerscdleary
bugs672893
milestone9.0a1
Bug 672893 - Don't #include jscompartment.h in xpconnect. r=cdleary.
js/jsd/jsd_xpc.cpp
js/src/Makefile.in
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsprvtd.h
js/src/xpconnect/loader/mozJSComponentLoader.cpp
js/src/xpconnect/src/nsXPConnect.cpp
js/src/xpconnect/src/xpcjsruntime.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcwrappednativescope.cpp
js/src/xpconnect/wrappers/AccessCheck.cpp
js/src/xpconnect/wrappers/AccessCheck.h
js/src/xpconnect/wrappers/CrossOriginWrapper.cpp
js/src/xpconnect/wrappers/WrapperFactory.cpp
js/src/xpconnect/wrappers/XrayWrapper.cpp
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -55,19 +55,16 @@
 #include "jsdebug.h"
 #include "nsReadableUtils.h"
 #include "nsCRT.h"
 
 /* XXX DOM dependency */
 #include "nsIScriptContext.h"
 #include "nsIJSContextStack.h"
 
-/* XXX private JS headers. */
-#include "jscompartment.h"
-
 /*
  * defining CAUTIOUS_SCRIPTHOOK makes jsds disable GC while calling out to the
  * script hook.  This was a hack to avoid some js engine problems that should
  * be fixed now (see Mozilla bug 77636).
  */
 #undef CAUTIOUS_SCRIPTHOOK
 
 #ifdef DEBUG_verbose
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -186,17 +186,16 @@ INSTALLED_HEADERS = \
 		jsdhash.h \
 		jsemit.h \
 		jsfun.h \
 		jsfriendapi.h \
 		jsgc.h \
 		jscell.h \
 		jsgcchunk.h \
 		jsgcstats.h \
-		jscompartment.h \
 		jshash.h \
 		jsinfer.h \
 		jsinferinlines.h \
 		jsinterp.h \
 		jsinttypes.h \
 		jsiter.h \
 		jslock.h \
 		jsobj.h \
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -39,16 +39,17 @@
 
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jsfriendapi.h"
 
 #include "jsobjinlines.h"
 
 using namespace js;
+using namespace JS;
 
 JS_FRIEND_API(JSString *)
 JS_GetAnonymousString(JSRuntime *rt)
 {
     JS_ASSERT(rt->state == JSRTS_UP);
     return rt->atomState.anonymousAtom;
 }
 
@@ -107,16 +108,63 @@ JS_NewObjectWithUniqueType(JSContext *cx
 JS_FRIEND_API(uint32)
 JS_ObjectCountDynamicSlots(JSObject *obj)
 {
     if (obj->hasSlotsArray())
         return obj->numDynamicSlots(obj->numSlots());
     return 0;
 }
 
+JS_FRIEND_API(JSPrincipals *)
+JS_GetCompartmentPrincipals(JSCompartment *compartment)
+{
+    return compartment->principals;
+}
+
+JS_FRIEND_API(JSBool)
+JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc)
+{
+    return cx->compartment->wrap(cx, desc);
+}
+
+AutoPreserveCompartment::AutoPreserveCompartment(JSContext *cx
+                                                 JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT)
+  : cx(cx), oldCompartment(cx->compartment)
+{
+    JS_GUARD_OBJECT_NOTIFIER_INIT;
+}
+
+AutoPreserveCompartment::~AutoPreserveCompartment()
+{
+    /* The old compartment may have been destroyed, so we can't use cx->setCompartment. */
+    cx->compartment = oldCompartment;
+}
+
+AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSCompartment *newCompartment
+                                             JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT)
+  : cx(cx), oldCompartment(cx->compartment)
+{
+    JS_GUARD_OBJECT_NOTIFIER_INIT;
+    cx->setCompartment(newCompartment);
+}
+
+AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSObject *target
+                                             JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT)
+  : cx(cx), oldCompartment(cx->compartment)
+{
+    JS_GUARD_OBJECT_NOTIFIER_INIT;
+    cx->setCompartment(target->compartment());
+}
+
+AutoSwitchCompartment::~AutoSwitchCompartment()
+{
+    /* The old compartment may have been destroyed, so we can't use cx->setCompartment. */
+    cx->compartment = oldCompartment;
+}
+
 /*
  * The below code is for temporary telemetry use. It can be removed when
  * sufficient data has been harvested.
  */
 
 extern size_t sE4XObjectsCreated;
 
 JS_FRIEND_API(size_t)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -88,11 +88,50 @@ typedef struct TypeInferenceMemoryStats
 extern JS_FRIEND_API(void)
 JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
                                TypeInferenceMemoryStats *stats);
 
 extern JS_FRIEND_API(void)
 JS_GetTypeInferenceObjectStats(/*TypeObject*/ void *object,
                                TypeInferenceMemoryStats *stats);
 
+extern JS_FRIEND_API(JSPrincipals *)
+JS_GetCompartmentPrincipals(JSCompartment *compartment);
+
+#ifdef __cplusplus
+
+extern JS_FRIEND_API(JSBool)
+JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc);
+
+#endif
+
 JS_END_EXTERN_C
 
+#ifdef __cplusplus
+
+namespace JS {
+
+class JS_FRIEND_API(AutoPreserveCompartment) {
+  private:
+    JSContext *cx;
+    JSCompartment *oldCompartment;
+  public:
+    AutoPreserveCompartment(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM);
+    ~AutoPreserveCompartment();
+    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+class JS_FRIEND_API(AutoSwitchCompartment) {
+  private:
+    JSContext *cx;
+    JSCompartment *oldCompartment;
+  public:
+    AutoSwitchCompartment(JSContext *cx, JSCompartment *newCompartment
+                          JS_GUARD_OBJECT_NOTIFIER_PARAM);
+    AutoSwitchCompartment(JSContext *cx, JSObject *target JS_GUARD_OBJECT_NOTIFIER_PARAM);
+    ~AutoSwitchCompartment();
+    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+}
+#endif
+
 #endif /* jsfriendapi_h___ */
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -180,16 +180,17 @@ class HashSet;
 
 template <typename K,
           typename V,
           size_t InlineElems>
 class InlineMap;
 
 class PropertyCache;
 struct PropertyCacheEntry;
+struct PropertyDescriptor;
 
 struct Shape;
 struct EmptyShape;
 class Bindings;
 
 class MultiDeclRange;
 class ParseMapPool;
 class DefnOrHeader;
--- a/js/src/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/src/xpconnect/loader/mozJSComponentLoader.cpp
@@ -69,17 +69,16 @@
 #include "nsString.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIURI.h"
 #include "nsIFileURL.h"
 #include "nsIJARURI.h"
 #include "nsNetUtil.h"
 #include "nsDOMFile.h"
 #include "jsxdrapi.h"
-#include "jscompartment.h"
 #include "jsprf.h"
 // For reporting errors with the console service
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIStorageStream.h"
 #include "nsIStringStream.h"
 #include "prmem.h"
 #if defined(XP_WIN)
@@ -747,18 +746,18 @@ mozJSComponentLoader::GlobalForLocation(
                                         jsval *exception)
 {
     nsresult rv;
 
     JSPrincipals* jsPrincipals = nsnull;
     JSCLContextHelper cx(this);
 
     // preserve caller's compartment
-    js::PreserveCompartment pc(cx);
-    
+    JS::AutoPreserveCompartment pc(cx);
+
     rv = mSystemPrincipal->GetJSPrincipals(cx, &jsPrincipals);
     NS_ENSURE_SUCCESS(rv, rv);
 
     JSPrincipalsHolder princHolder(mContext, jsPrincipals);
 
     nsCOMPtr<nsIXPCScriptable> backstagePass;
     rv = mRuntimeService->GetBackstagePass(getter_AddRefs(backstagePass));
     NS_ENSURE_SUCCESS(rv, rv);
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -1058,17 +1058,17 @@ CreateNewCompartment(JSContext *cx, JSCl
         JSPRINCIPALS_DROP(cx, principals);
 
     if(!tempGlobal)
         return false;
 
     *global = tempGlobal;
     *compartment = tempGlobal->compartment();
 
-    js::SwitchToCompartment sc(cx, *compartment);
+    JS::AutoSwitchCompartment sc(cx, *compartment);
     JS_SetCompartmentPrivate(cx, *compartment, priv_holder.forget());
     return true;
 }
 
 nsresult
 xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
                        nsIPrincipal *principal, nsISupports *ptr,
                        bool wantXrays, JSObject **global,
@@ -1090,17 +1090,17 @@ xpc_CreateGlobalObject(JSContext *cx, JS
         {
             return UnexpectedFailure(NS_ERROR_FAILURE);
         }
 
         map.Put(&key, *compartment);
     }
     else
     {
-        js::SwitchToCompartment sc(cx, *compartment);
+        JS::AutoSwitchCompartment sc(cx, *compartment);
 
         JSObject *tempGlobal = JS_NewGlobalObject(cx, clasp);
         if(!tempGlobal)
             return UnexpectedFailure(NS_ERROR_FAILURE);
         *global = tempGlobal;
     }
 
     return NS_OK;
@@ -1127,17 +1127,17 @@ xpc_CreateMTGlobalObject(JSContext *cx, 
         {
             return UnexpectedFailure(NS_ERROR_UNEXPECTED);
         }
 
         map.Put(ptr, *compartment);
     }
     else
     {
-        js::SwitchToCompartment sc(cx, *compartment);
+        JS::AutoSwitchCompartment sc(cx, *compartment);
 
         JSObject *tempGlobal = JS_NewGlobalObject(cx, clasp);
         if(!tempGlobal)
             return UnexpectedFailure(NS_ERROR_FAILURE);
         *global = tempGlobal;
     }
 
     return NS_OK;
@@ -2560,17 +2560,17 @@ nsXPConnect::CheckForDebugMode(JSRuntime
             AutoDestroyContext(JSContext *cx) : cx(cx) {}
             ~AutoDestroyContext() { JS_DestroyContext(cx); }
         } adc(cx);
         JSAutoRequest ar(cx);
 
         js::CompartmentVector &vector = rt->compartments;
         for (JSCompartment **p = vector.begin(); p != vector.end(); ++p) {
             JSCompartment *comp = *p;
-            if (!comp->principals) {
+            if (!JS_GetCompartmentPrincipals(comp)) {
                 /* Ignore special compartments (atoms, JSD compartments) */
                 continue;
             }
 
             /* ParticipatesInCycleCollection means "on the main thread" */
             if (xpc::CompartmentParticipatesInCycleCollection(cx, comp)) {
                 if (!JS_SetDebugModeForCompartment(cx, comp, gDesiredDebugMode))
                     goto fail;
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -100,18 +100,18 @@ WrappedJSDyingJSObjectFinder(JSDHashTabl
     nsXPCWrappedJS* wrapper = ((JSObject2WrappedJSMap::Entry*)hdr)->value;
     NS_ASSERTION(wrapper, "found a null JS wrapper!");
 
     // walk the wrapper chain and find any whose JSObject is to be finalized
     while(wrapper)
     {
         if(wrapper->IsSubjectToFinalization())
         {
-            js::SwitchToCompartment sc(data->cx,
-                                       wrapper->GetJSObjectPreserveColor());
+            JS::AutoSwitchCompartment sc(data->cx,
+                                         wrapper->GetJSObjectPreserveColor());
             if(JS_IsAboutToBeFinalized(data->cx,
                                        wrapper->GetJSObjectPreserveColor()))
                 data->array->AppendElement(wrapper);
         }
         wrapper = wrapper->GetNextWrapper();
     }
     return JS_DHASH_NEXT;
 }
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -53,18 +53,18 @@
 #include "xpcpublic.h"
 #include "jsapi.h"
 #include "jsdhash.h"
 #include "jsprf.h"
 #include "prprf.h"
 #include "jsinterp.h"
 #include "jscntxt.h"
 #include "jsdbgapi.h"
+#include "jsfriendapi.h"
 #include "jsgc.h"
-#include "jscompartment.h"
 #include "nscore.h"
 #include "nsXPCOM.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCycleCollector.h"
 #include "nsDebug.h"
 #include "nsISupports.h"
 #include "nsIServiceManager.h"
--- a/js/src/xpconnect/src/xpcwrappednativescope.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp
@@ -437,17 +437,17 @@ XPCWrappedNativeScope::FinishedMarkPhase
 
     XPCWrappedNativeScope* prev = nsnull;
     XPCWrappedNativeScope* cur = gScopes;
 
     while(cur)
     {
         XPCWrappedNativeScope* next = cur->mNext;
 
-        js::SwitchToCompartment sc(cx, cur->mGlobalJSObject);
+        JS::AutoSwitchCompartment sc(cx, cur->mGlobalJSObject);
 
         if(cur->mGlobalJSObject &&
            JS_IsAboutToBeFinalized(cx, cur->mGlobalJSObject))
         {
             cur->mGlobalJSObject = nsnull;
             cur->mScriptObjectPrincipal = nsnull;
             // Move this scope from the live list to the dying list.
             if(prev)
--- a/js/src/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/src/xpconnect/wrappers/AccessCheck.cpp
@@ -48,20 +48,21 @@
 #include "XrayWrapper.h"
 #include "FilteringWrapper.h"
 #include "WrapperFactory.h"
 
 #include "jsfriendapi.h"
 
 namespace xpc {
 
-static nsIPrincipal *
+nsIPrincipal *
 GetCompartmentPrincipal(JSCompartment *compartment)
 {
-    return compartment->principals ? static_cast<nsJSPrincipals *>(compartment->principals)->nsIPrincipalPtr : 0;
+    JSPrincipals *prin = JS_GetCompartmentPrincipals(compartment);
+    return prin ? static_cast<nsJSPrincipals *>(prin)->nsIPrincipalPtr : nsnull;
 }
 
 bool
 AccessCheck::isSameOrigin(JSCompartment *a, JSCompartment *b)
 {
     nsIPrincipal *aprin = GetCompartmentPrincipal(a);
     nsIPrincipal *bprin = GetCompartmentPrincipal(b);
 
--- a/js/src/xpconnect/wrappers/AccessCheck.h
+++ b/js/src/xpconnect/wrappers/AccessCheck.h
@@ -39,16 +39,19 @@
 
 #include "jsapi.h"
 #include "jswrapper.h"
 
 class nsIPrincipal;
 
 namespace xpc {
 
+nsIPrincipal *
+GetCompartmentPrincipal(JSCompartment *compartment);
+
 class AccessCheck {
   public:
     static bool isSameOrigin(JSCompartment *a, JSCompartment *b);
     static bool isChrome(JSCompartment *compartment);
     static nsIPrincipal *getPrincipal(JSCompartment *compartment);
     static bool isCrossOriginAccessPermitted(JSContext *cx, JSObject *obj, jsid id,
                                              JSWrapper::Action act);
     static bool isSystemOnlyAccessPermitted(JSContext *cx);
--- a/js/src/xpconnect/wrappers/CrossOriginWrapper.cpp
+++ b/js/src/xpconnect/wrappers/CrossOriginWrapper.cpp
@@ -37,16 +37,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsJSPrincipals.h"
 
 #include "XPCWrapper.h"
 
 #include "CrossOriginWrapper.h"
+#include "AccessCheck.h"
 #include "WrapperFactory.h"
 
 namespace xpc {
 
 NoWaiverWrapper::NoWaiverWrapper(uintN flags) : JSCrossCompartmentWrapper(flags)
 {
 }
 
@@ -57,22 +58,16 @@ NoWaiverWrapper::~NoWaiverWrapper()
 CrossOriginWrapper::CrossOriginWrapper(uintN flags) : NoWaiverWrapper(flags)
 {
 }
 
 CrossOriginWrapper::~CrossOriginWrapper()
 {
 }
 
-static nsIPrincipal *
-GetCompartmentPrincipal(JSCompartment *compartment)
-{
-    return static_cast<nsJSPrincipals *>(compartment->principals)->nsIPrincipalPtr;
-}
-
 bool
 CrossOriginWrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
                                           bool set, js::PropertyDescriptor *desc)
 {
     return JSCrossCompartmentWrapper::getPropertyDescriptor(cx, wrapper, id, set, desc) &&
            WrapperFactory::WaiveXrayAndWrap(cx, js::Jsvalify(&desc->value));
 }
 
--- a/js/src/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/src/xpconnect/wrappers/WrapperFactory.cpp
@@ -260,17 +260,18 @@ WrapperFactory::Rewrap(JSContext *cx, JS
                  "wrapped object passed to rewrap");
     NS_ASSERTION(JS_GET_CLASS(cx, obj) != &XrayUtils::HolderClass, "trying to wrap a holder");
 
     JSCompartment *origin = obj->compartment();
     JSCompartment *target = cx->compartment;
     JSObject *xrayHolder = nsnull;
 
     JSWrapper *wrapper;
-    CompartmentPrivate *targetdata = static_cast<CompartmentPrivate *>(target->data);
+    CompartmentPrivate *targetdata =
+        static_cast<CompartmentPrivate *>(JS_GetCompartmentPrivate(cx, target));
     if (AccessCheck::isChrome(target)) {
         if (AccessCheck::isChrome(origin)) {
             wrapper = &JSCrossCompartmentWrapper::singleton;
         } else {
             bool isSystem;
             {
                 JSAutoEnterCompartment ac;
                 if (!ac.enter(cx, obj))
--- a/js/src/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/src/xpconnect/wrappers/XrayWrapper.cpp
@@ -551,17 +551,17 @@ XrayWrapper<Base>::getPropertyDescriptor
             if (!JS_GetPropertyDescriptorById(cx, wnObject, id,
                                               (set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED,
                                               desc))
                 return false;
         }
 
         if (desc->obj)
             desc->obj = wrapper;
-        return cx->compartment->wrap(cx, desc_in);
+        return JS_WrapPropertyDescriptor(cx, desc_in);
     }
 
     if (!this->resolveOwnProperty(cx, wrapper, id, set, desc_in))
         return false;
 
     if (desc->obj)
         return true;
 
@@ -622,17 +622,17 @@ XrayWrapper<Base>::getOwnPropertyDescrip
             if (!JS_GetPropertyDescriptorById(cx, wnObject, id,
                                               (set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED,
                                               desc)) {
                 return false;
             }
         }
 
         desc->obj = (desc->obj == wnObject) ? wrapper : nsnull;
-        return cx->compartment->wrap(cx, desc_in);
+        return JS_WrapPropertyDescriptor(cx, desc_in);
     }
 
     return this->resolveOwnProperty(cx, wrapper, id, set, desc_in);
 }
 
 template <typename Base>
 bool
 XrayWrapper<Base>::defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
@@ -644,17 +644,17 @@ XrayWrapper<Base>::defineProperty(JSCont
     // Redirect access straight to the wrapper if we should be transparent.
     if (Transparent(cx, wrapper)) {
         JSObject *wnObject = GetWrappedNativeObjectFromHolder(holder);
 
         JSAutoEnterCompartment ac;
         if (!ac.enter(cx, wnObject))
             return false;
 
-        if (!cx->compartment->wrap(cx, desc))
+        if (!JS_WrapPropertyDescriptor(cx, desc))
             return false;
 
         return JS_DefinePropertyById(cx, wnObject, id, jsdesc->value, jsdesc->getter, jsdesc->setter,
                                      jsdesc->attrs);
     }
 
     PropertyDescriptor existing_desc;
     if (!getOwnPropertyDescriptor(cx, wrapper, id, true, &existing_desc))