Bug 1049440 - Don't crash in jsapi-tests when a test fails to initialize r=luke
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 13 Aug 2014 10:03:45 +0100
changeset 199206 fb4ffdf1f64711b5dd2eac817eeacdc95298aaee
parent 199205 9ffe3e743ffccfd1824a3853fa16373e7c0fe376
child 199207 a817b58630c872cfef3c9f84f7b9bd707a8147a5
push id8185
push useremorley@mozilla.com
push dateWed, 13 Aug 2014 16:01:50 +0000
treeherderfx-team@1601bb449713 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1049440
milestone34.0a1
Bug 1049440 - Don't crash in jsapi-tests when a test fails to initialize r=luke
js/src/jsapi-tests/tests.cpp
js/src/jsapi-tests/tests.h
--- a/js/src/jsapi-tests/tests.cpp
+++ b/js/src/jsapi-tests/tests.cpp
@@ -23,16 +23,38 @@ bool JSAPITest::init()
     JS_BeginRequest(cx);
     JS::RootedObject global(cx, createGlobal());
     if (!global)
         return false;
     JS_EnterCompartment(cx, global);
     return true;
 }
 
+void JSAPITest::uninit()
+{
+    if (oldCompartment) {
+        JS_LeaveCompartment(cx, oldCompartment);
+        oldCompartment = nullptr;
+    }
+    if (global) {
+        JS_LeaveCompartment(cx, nullptr);
+        JS::RemoveObjectRoot(cx, &global);
+        global = nullptr;
+    }
+    if (cx) {
+        JS_EndRequest(cx);
+        JS_DestroyContext(cx);
+        cx = nullptr;
+    }
+    if (rt) {
+        destroyRuntime();
+        rt = nullptr;
+    }
+}
+
 bool JSAPITest::exec(const char *bytes, const char *filename, int lineno)
 {
     JS::RootedValue v(cx);
     JS::HandleObject global = JS::HandleObject::fromMarkedLocation(this->global.unsafeGet());
     return JS_EvaluateScript(cx, global, bytes, strlen(bytes), filename, lineno, &v) ||
         fail(JSAPITestString(bytes), filename, lineno);
 }
 
@@ -59,18 +81,21 @@ JSObject * JSAPITest::createGlobal(JSPri
     if (!global)
         return nullptr;
     JS::AddNamedObjectRoot(cx, &global, "test-global");
     JS::HandleObject globalHandle = JS::HandleObject::fromMarkedLocation(global.unsafeGet());
     JSAutoCompartment ac(cx, globalHandle);
 
     /* Populate the global object with the standard globals, like Object and
        Array. */
-    if (!JS_InitStandardClasses(cx, globalHandle))
-        return nullptr;
+    if (!JS_InitStandardClasses(cx, globalHandle)) {
+        global = nullptr;
+        JS::RemoveObjectRoot(cx, &global);
+    }
+
     return global;
 }
 
 int main(int argc, char *argv[])
 {
     int total = 0;
     int failures = 0;
     const char *filter = (argc == 2) ? argv[1] : nullptr;
@@ -86,16 +111,17 @@ int main(int argc, char *argv[])
             continue;
 
         total += 1;
 
         printf("%s\n", name);
         if (!test->init()) {
             printf("TEST-UNEXPECTED-FAIL | %s | Failed to initialize.\n", name);
             failures++;
+            test->uninit();
             continue;
         }
 
         JS::HandleObject global = JS::HandleObject::fromMarkedLocation(test->global.unsafeGet());
         if (test->run(global)) {
             printf("TEST-PASS | %s | ok\n", name);
         } else {
             JSAPITestString messages = test->messages();
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -62,38 +62,24 @@ class JSAPITest
     JSCompartment *oldCompartment;
 
     JSAPITest() : rt(nullptr), cx(nullptr), global(nullptr),
                   knownFail(false), oldCompartment(nullptr) {
         next = list;
         list = this;
     }
 
-    virtual ~JSAPITest() { uninit(); }
+    virtual ~JSAPITest() {
+        JS_ASSERT(!rt);
+        JS_ASSERT(!cx);
+        JS_ASSERT(!global);
+    }
 
     virtual bool init();
-
-    virtual void uninit() {
-        if (oldCompartment) {
-            JS_LeaveCompartment(cx, oldCompartment);
-            oldCompartment = nullptr;
-        }
-        global = nullptr;
-        if (cx) {
-            JS::RemoveObjectRoot(cx, &global);
-            JS_LeaveCompartment(cx, nullptr);
-            JS_EndRequest(cx);
-            JS_DestroyContext(cx);
-            cx = nullptr;
-        }
-        if (rt) {
-            destroyRuntime();
-            rt = nullptr;
-        }
-    }
+    virtual void uninit();
 
     virtual const char * name() = 0;
     virtual bool run(JS::HandleObject global) = 0;
 
 #define EXEC(s) do { if (!exec(s, __FILE__, __LINE__)) return false; } while (false)
 
     bool exec(const char *bytes, const char *filename, int lineno);