Bug 899367 - Add an API to opt out of default compartment objects. r=luke
authorBobby Holley <bobbyholley@gmail.com>
Wed, 04 Sep 2013 14:06:55 -0700
changeset 145508 6ca662ba7c557d378bd2641dc737c5c031ba9e58
parent 145507 bb9646daf4c382ba31f91df5acd20a6e62a5fb38
child 145509 14df512b792aeb64e3608f4e4de70151a411f354
push id33304
push userbobbyholley@gmail.com
push dateWed, 04 Sep 2013 21:07:07 +0000
treeherdermozilla-inbound@dd6d206a9a8a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs899367
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 899367 - Add an API to opt out of default compartment objects. r=luke We need this explicit API because otherwise the default compartment object will get set implicitly during the first call to InitClasses.
js/src/jsapi.h
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/vm/SelfHosting.cpp
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1521,17 +1521,21 @@ JS_StringToVersion(const char *string);
                                                    uncaught exceptions from
                                                    being converted to error
                                                    reports */
 
 /* JS_BIT(9) is currently unused. */
 
 /* JS_BIT(10) is currently unused. */
 
-/* JS_BIT(11) is currently unused. */
+#define JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT JS_BIT(11)     /* This JSContext does not use a
+                                                                 default compartment object. Such
+                                                                 an object will not be set implicitly,
+                                                                 and attempts to get or set it will
+                                                                 assert. */
 
 #define JSOPTION_NO_SCRIPT_RVAL JS_BIT(12)      /* A promise to the compiler
                                                    that a null rval out-param
                                                    will be passed to each call
                                                    to JS_ExecuteScript. */
 #define JSOPTION_UNROOTED_GLOBAL JS_BIT(13)     /* The GC will not root the
                                                    contexts' default compartment
                                                    object, leaving that up to the
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -444,17 +444,20 @@ struct JSContext : public js::ExclusiveC
      * compartment will be set to the compartment of the "default compartment
      * object".
      */
   private:
     JSObject *defaultCompartmentObject_;
   public:
     inline void setDefaultCompartmentObject(JSObject *obj);
     inline void setDefaultCompartmentObjectIfUnset(JSObject *obj);
-    JSObject *maybeDefaultCompartmentObject() const { return defaultCompartmentObject_; }
+    JSObject *maybeDefaultCompartmentObject() const {
+        JS_ASSERT(!hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT));
+        return defaultCompartmentObject_;
+    }
 
     /* Wrap cx->exception for the current compartment. */
     void wrapPendingException();
 
     /* State for object and array toSource conversion. */
     js::ObjectSet       cycleDetectorSet;
 
     /* Per-context optional error reporter. */
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -433,24 +433,28 @@ JSContext::setPendingException(js::Value
     this->throwing = true;
     this->exception = v;
     js::assertSameCompartment(this, v);
 }
 
 inline void
 JSContext::setDefaultCompartmentObject(JSObject *obj)
 {
+    JS_ASSERT(!hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT));
     defaultCompartmentObject_ = obj;
 }
 
 inline void
 JSContext::setDefaultCompartmentObjectIfUnset(JSObject *obj)
 {
-    if (!defaultCompartmentObject_)
+    if (!hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT) &&
+        !defaultCompartmentObject_)
+    {
         setDefaultCompartmentObject(obj);
+    }
 }
 
 inline void
 js::ExclusiveContext::enterCompartment(JSCompartment *c)
 {
     enterCompartmentDepth_++;
     c->enter();
     setCompartment(c);
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -677,22 +677,27 @@ const JSFunctionSpec intrinsic_functions
 
     JS_FS_END
 };
 
 bool
 JSRuntime::initSelfHosting(JSContext *cx)
 {
     JS_ASSERT(!selfHostingGlobal_);
-    RootedObject savedGlobal(cx, js::DefaultObjectForContextOrNull(cx));
+
+    bool receivesDefaultObject = !cx->hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT);
+    RootedObject savedGlobal(cx, receivesDefaultObject
+                                 ? js::DefaultObjectForContextOrNull(cx)
+                                 : NULL);
     if (!(selfHostingGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class,
                                                   NULL, JS::DontFireOnNewGlobalHook)))
         return false;
     JSAutoCompartment ac(cx, selfHostingGlobal_);
-    js::SetDefaultObjectForContext(cx, selfHostingGlobal_);
+    if (receivesDefaultObject)
+        js::SetDefaultObjectForContext(cx, selfHostingGlobal_);
     Rooted<GlobalObject*> shg(cx, &selfHostingGlobal_->as<GlobalObject>());
     /*
      * During initialization of standard classes for the self-hosting global,
      * all self-hosted functions are ignored. Thus, we don't create cyclic
      * dependencies in the order of initialization.
      */
     if (!GlobalObject::initStandardClasses(cx, shg))
         return false;
@@ -751,17 +756,18 @@ JSRuntime::initSelfHosting(JSContext *cx
         }
 #else
         const char *src = rawSources;
 #endif
 
         ok = Evaluate(cx, shg, options, src, srcLen, &rv);
     }
     JS_SetErrorReporter(cx, oldReporter);
-    js::SetDefaultObjectForContext(cx, savedGlobal);
+    if (receivesDefaultObject)
+        js::SetDefaultObjectForContext(cx, savedGlobal);
     return ok;
 }
 
 void
 JSRuntime::finishSelfHosting()
 {
     selfHostingGlobal_ = NULL;