Bug 1049440 - Don't crash in jsapi-tests when a test fails to initialize r=luke
--- 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);