Bug 1022773 - Switch all JS Compile functions to use MutableHandle, r=terrence
authorSteve Fink <sfink@mozilla.com>
Wed, 25 Jun 2014 15:35:35 -0700
changeset 213618 830b491a8fa36f617a79247eeb4773fd0a718639
parent 213617 d4bd5c2fdce2b30fc4aa287e6cfce19e20371664
child 213619 073ff2d2db9c2c8ea2cd7f2ff0ad52d219e6c0ff
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1022773
milestone33.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 1022773 - Switch all JS Compile functions to use MutableHandle, r=terrence
dom/base/nsJSUtils.cpp
ipc/testshell/XPCShellEnvironment.cpp
js/src/jsapi-tests/testChromeBuffer.cpp
js/src/jsapi-tests/testCloneScript.cpp
js/src/jsapi-tests/testEnclosingFunction.cpp
js/src/jsapi-tests/testScriptInfo.cpp
js/src/jsapi-tests/testScriptObject.cpp
js/src/jsapi-tests/testSourcePolicy.cpp
js/src/jsapi-tests/testTrap.cpp
js/src/jsapi-tests/testXDR.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/shell/js.cpp
js/src/vm/SelfHosting.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/src/XPCShellImpl.cpp
netwerk/base/src/ProxyAutoConfig.cpp
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -152,22 +152,23 @@ nsJSUtils::CompileFunction(JSContext* aC
   MOZ_ASSERT_IF(ctx, ctx->IsContextInitialized());
 
   // Do the junk Gecko is supposed to do before calling into JSAPI.
   if (aTarget) {
     JS::ExposeObjectToActiveJS(aTarget);
   }
 
   // Compile.
-  JSFunction* fun = JS::CompileFunction(aCx, aTarget, aOptions,
-                                        PromiseFlatCString(aName).get(),
-                                        aArgCount, aArgArray,
-                                        PromiseFlatString(aBody).get(),
-                                        aBody.Length());
-  if (!fun) {
+  JS::Rooted<JSFunction*> fun(aCx);
+  if (!JS::CompileFunction(aCx, aTarget, aOptions,
+                           PromiseFlatCString(aName).get(),
+                           aArgCount, aArgArray,
+                           PromiseFlatString(aBody).get(),
+                           aBody.Length(), &fun))
+  {
     ReportPendingException(aCx);
     return NS_ERROR_FAILURE;
   }
 
   *aFunctionObject = JS_GetFunctionObject(fun);
   return NS_OK;
 }
 
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -160,19 +160,20 @@ Load(JSContext *cx,
         if (!file) {
             JS_ReportError(cx, "cannot open file '%s' for reading", filename.ptr());
             return false;
         }
         Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
         JS::CompileOptions options(cx);
         options.setUTF8(true)
                .setFileAndLine(filename.ptr(), 1);
-        JS::Rooted<JSScript*> script(cx, JS::Compile(cx, obj, options, file));
+        JS::Rooted<JSScript*> script(cx);
+        bool ok = JS::Compile(cx, obj, options, file, &script);
         fclose(file);
-        if (!script)
+        if (!ok)
             return false;
 
         if (!JS_ExecuteScript(cx, obj, script)) {
             return false;
         }
     }
     args.rval().setUndefined();
     return true;
@@ -329,18 +330,18 @@ XPCShellEnvironment::ProcessFile(JSConte
         ungetc(ch, file);
 
         JSAutoRequest ar(cx);
         JSAutoCompartment ac(cx, obj);
 
         JS::CompileOptions options(cx);
         options.setUTF8(true)
                .setFileAndLine(filename, 1);
-        JS::Rooted<JSScript*> script(cx, JS::Compile(cx, obj, options, file));
-        if (script)
+        JS::Rooted<JSScript*> script(cx);
+        if (JS::Compile(cx, obj, options, file, &script))
             (void)JS_ExecuteScript(cx, obj, script, &result);
 
         return;
     }
 
     /* It's an interactive filehandle; drop into read-eval-print loop. */
     lineno = 1;
     hitEOF = false;
@@ -366,19 +367,18 @@ XPCShellEnvironment::ProcessFile(JSConte
             bufp += strlen(bufp);
             lineno++;
         } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
 
         /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
         JS::CompileOptions options(cx);
         options.setFileAndLine("typein", startline);
-        JS::Rooted<JSScript*> script(cx,
-                                     JS_CompileScript(cx, obj, buffer, strlen(buffer), options));
-        if (script) {
+        JS::Rooted<JSScript*> script(cx);
+        if (JS_CompileScript(cx, obj, buffer, strlen(buffer), options, &script)) {
             JSErrorReporter older;
 
             ok = JS_ExecuteScript(cx, obj, script, &result);
             if (ok && result != JSVAL_VOID) {
                 /* Suppress error reports from JS::ToString(). */
                 older = JS_SetErrorReporter(cx, nullptr);
                 str = JS::ToString(cx, result);
                 JSAutoByteString bytes;
@@ -575,19 +575,20 @@ XPCShellEnvironment::EvaluateString(cons
                                     nsString* aResult)
 {
   AutoSafeJSContext cx;
   JS::Rooted<JSObject*> global(cx, GetGlobalObject());
   JSAutoCompartment ac(cx, global);
 
   JS::CompileOptions options(cx);
   options.setFileAndLine("typein", 0);
-  JS::Rooted<JSScript*> script(cx, JS_CompileUCScript(cx, global, aString.get(),
-                                                      aString.Length(), options));
-  if (!script) {
+  JS::Rooted<JSScript*> script(cx);
+  if (!JS_CompileUCScript(cx, global, aString.get(), aString.Length(), options,
+                          &script))
+  {
      return false;
   }
 
   if (aResult) {
       aResult->Truncate();
   }
 
   JS::Rooted<JS::Value> result(cx);
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -66,18 +66,18 @@ BEGIN_TEST(testChromeBuffer)
     {
         {
             JSAutoCompartment ac(cx, trusted_glob);
             const char *paramName = "x";
             const char *bytes = "return x ? 1 + trusted(x-1) : 0";
             JS::HandleObject global = JS::HandleObject::fromMarkedLocation(trusted_glob.unsafeGet());
             JS::CompileOptions options(cx);
             options.setFileAndLine("", 0);
-            CHECK(fun = JS_CompileFunction(cx, global, "trusted", 1, &paramName,
-                                           bytes, strlen(bytes), options));
+            CHECK(JS_CompileFunction(cx, global, "trusted", 1, &paramName,
+                                     bytes, strlen(bytes), options, &fun));
             trusted_fun = JS_GetFunctionObject(fun);
             if (!JS::AddNamedObjectRoot(cx, &trusted_fun, "trusted-function"))
                 return false;
         }
 
         JS::RootedValue v(cx, JS::ObjectValue(*trusted_fun));
         CHECK(JS_WrapValue(cx, &v));
 
@@ -88,18 +88,18 @@ BEGIN_TEST(testChromeBuffer)
                             "    try {                                  "
                             "        return trusted(100);               "
                             "    } catch(e) {                           "
                             "        return -1;                         "
                             "    }                                      "
                             "}                                          ";
         JS::CompileOptions options(cx);
         options.setFileAndLine("", 0);
-        CHECK(fun = JS_CompileFunction(cx, global, "untrusted", 1, &paramName,
-                                       bytes, strlen(bytes), options));
+        CHECK(JS_CompileFunction(cx, global, "untrusted", 1, &paramName,
+                                 bytes, strlen(bytes), options, &fun));
 
         JS::RootedValue rval(cx);
         CHECK(JS_CallFunction(cx, JS::NullPtr(), fun, JS::HandleValueArray(v), &rval));
         CHECK(rval.toInt32() == 100);
     }
 
     /*
      * Check that content called from chrome in the reserved-buffer space
@@ -112,34 +112,34 @@ BEGIN_TEST(testChromeBuffer)
             const char *bytes = "try {                                  "
                                 "  untrusted();                         "
                                 "} catch (e) {                          "
                                 "  return 'From trusted: ' + e;         "
                                 "}                                      ";
             JS::HandleObject global = JS::HandleObject::fromMarkedLocation(trusted_glob.unsafeGet());
             JS::CompileOptions options(cx);
             options.setFileAndLine("", 0);
-            CHECK(fun = JS_CompileFunction(cx, global, "trusted", 1, &paramName,
-                                           bytes, strlen(bytes), options));
+            CHECK(JS_CompileFunction(cx, global, "trusted", 1, &paramName,
+                                     bytes, strlen(bytes), options, &fun));
             trusted_fun = JS_GetFunctionObject(fun);
         }
 
         JS::RootedValue v(cx, JS::ObjectValue(*trusted_fun));
         CHECK(JS_WrapValue(cx, &v));
 
         const char *paramName = "trusted";
         const char *bytes = "try {                                      "
                             "  return untrusted(trusted);               "
                             "} catch (e) {                              "
                             "  return trusted(untrusted);               "
                             "}                                          ";
         JS::CompileOptions options(cx);
         options.setFileAndLine("", 0);
-        CHECK(fun = JS_CompileFunction(cx, global, "untrusted", 1, &paramName,
-                                       bytes, strlen(bytes), options));
+        CHECK(JS_CompileFunction(cx, global, "untrusted", 1, &paramName,
+                                 bytes, strlen(bytes), options, &fun));
 
         JS::RootedValue rval(cx);
         CHECK(JS_CallFunction(cx, JS::NullPtr(), fun, JS::HandleValueArray(v), &rval));
         bool match;
         CHECK(JS_StringEqualsAscii(cx, rval.toString(), "From trusted: InternalError: too much recursion", &match));
         CHECK(match);
     }
 
@@ -149,34 +149,34 @@ BEGIN_TEST(testChromeBuffer)
      */
     {
         {
             JSAutoCompartment ac(cx, trusted_glob);
             const char *bytes = "return 42";
             JS::HandleObject global = JS::HandleObject::fromMarkedLocation(trusted_glob.unsafeGet());
             JS::CompileOptions options(cx);
             options.setFileAndLine("", 0);
-            CHECK(fun = JS_CompileFunction(cx, global, "trusted", 0, nullptr,
-                                           bytes, strlen(bytes), options));
+            CHECK(JS_CompileFunction(cx, global, "trusted", 0, nullptr,
+                                     bytes, strlen(bytes), options, &fun));
             trusted_fun = JS_GetFunctionObject(fun);
         }
 
         JS::RootedFunction fun(cx, JS_NewFunction(cx, CallTrusted, 0, 0, global, "callTrusted"));
         JS::RootedObject callTrusted(cx, JS_GetFunctionObject(fun));
 
         const char *paramName = "f";
         const char *bytes = "try {                                      "
                             "  return untrusted(trusted);               "
                             "} catch (e) {                              "
                             "  return f();                              "
                             "}                                          ";
         JS::CompileOptions options(cx);
         options.setFileAndLine("", 0);
-        CHECK(fun = JS_CompileFunction(cx, global, "untrusted", 1, &paramName,
-                                       bytes, strlen(bytes), options));
+        CHECK(JS_CompileFunction(cx, global, "untrusted", 1, &paramName,
+                                 bytes, strlen(bytes), options, &fun));
 
         JS::RootedValue arg(cx, JS::ObjectValue(*callTrusted));
         JS::RootedValue rval(cx);
         CHECK(JS_CallFunction(cx, JS::NullPtr(), fun, JS::HandleValueArray(arg), &rval));
         CHECK(rval.toInt32() == 42);
     }
 
     return true;
--- a/js/src/jsapi-tests/testCloneScript.cpp
+++ b/js/src/jsapi-tests/testCloneScript.cpp
@@ -28,21 +28,21 @@ BEGIN_TEST(test_cloneScript)
         "}\n"
         "(sum);\n";
 
     JS::RootedObject obj(cx);
 
     // compile for A
     {
         JSAutoCompartment a(cx, A);
-        JSFunction *fun;
+        JS::RootedFunction fun(cx);
         JS::CompileOptions options(cx);
         options.setFileAndLine(__FILE__, 1);
-        CHECK(fun = JS_CompileFunction(cx, A, "f", 0, nullptr, source,
-                                       strlen(source), options));
+        CHECK(JS_CompileFunction(cx, A, "f", 0, nullptr, source,
+                                 strlen(source), options, &fun));
         CHECK(obj = JS_GetFunctionObject(fun));
     }
 
     // clone into B
     {
         JSAutoCompartment b(cx, B);
         CHECK(JS_CloneFunctionObject(cx, obj, B));
     }
@@ -104,19 +104,20 @@ BEGIN_TEST(test_cloneScriptWithPrincipal
 
     JS::RootedObject obj(cx);
 
     // Compile in A
     {
         JSAutoCompartment a(cx, A);
         JS::CompileOptions options(cx);
         options.setFileAndLine(__FILE__, 1);
-        JS::RootedFunction fun(cx, JS_CompileFunction(cx, A, "f",
-                mozilla::ArrayLength(argnames), argnames, source,
-                strlen(source), options));
+        JS::RootedFunction fun(cx);
+        JS_CompileFunction(cx, A, "f",
+                           mozilla::ArrayLength(argnames), argnames, source,
+                           strlen(source), options, &fun);
         CHECK(fun);
 
         JSScript *script;
         CHECK(script = JS_GetFunctionScript(cx, fun));
 
         CHECK(JS_GetScriptPrincipals(script) == principalsA);
         CHECK(obj = JS_GetFunctionObject(fun));
     }
--- a/js/src/jsapi-tests/testEnclosingFunction.cpp
+++ b/js/src/jsapi-tests/testEnclosingFunction.cpp
@@ -35,31 +35,31 @@ BEGIN_TEST(test_enclosingFunction)
     CHECK(foundFun == nullptr);
 
     RootedFunction fun(cx);
 
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
 
     const char s1chars[] = "checkEnclosing()";
-    fun = JS_CompileFunction(cx, global, "s1", 0, nullptr, s1chars,
-                             strlen(s1chars), options);
+    JS_CompileFunction(cx, global, "s1", 0, nullptr, s1chars,
+                       strlen(s1chars), options, &fun);
     CHECK(fun);
     EXEC("s1()");
     CHECK(foundFun == fun);
 
     const char s2chars[] = "return function() { checkEnclosing() }";
-    fun = JS_CompileFunction(cx, global, "s2", 0, nullptr, s2chars,
-                             strlen(s2chars), options);
+    JS_CompileFunction(cx, global, "s2", 0, nullptr, s2chars,
+                       strlen(s2chars), options, &fun);
     CHECK(fun);
     EXEC("s2()()");
     CHECK(foundFun == fun);
 
     const char s3chars[] = "return function() { let (x) { function g() { checkEnclosing() } return g() } }";
-    fun = JS_CompileFunction(cx, global, "s3", 0, nullptr, s3chars,
-                             strlen(s3chars), options);
+    JS_CompileFunction(cx, global, "s3", 0, nullptr, s3chars,
+                       strlen(s3chars), options, &fun);
     CHECK(fun);
     EXEC("s3()()");
     CHECK(foundFun == fun);
 
     return true;
 }
 END_TEST(test_enclosingFunction)
--- a/js/src/jsapi-tests/testScriptInfo.cpp
+++ b/js/src/jsapi-tests/testScriptInfo.cpp
@@ -24,19 +24,18 @@ catch (e)          \n\
 
 // Bug 670958 - fix JS_GetScriptLineExtent, among others
 BEGIN_TEST(testScriptInfo)
 {
     unsigned startLine = 1000;
 
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, startLine);
-    JS::RootedScript script(cx, JS_CompileScript(cx, global, code, strlen(code),
-                                                 options));
-
+    JS::RootedScript script(cx);
+    CHECK(JS_CompileScript(cx, global, code, strlen(code), options, &script));
     CHECK(script);
 
     jsbytecode *start = JS_LineNumberToPC(cx, script, startLine);
     CHECK_EQUAL(JS_GetScriptBaseLineNumber(cx, script), startLine);
     CHECK_EQUAL(JS_PCToLineNumber(cx, script, start), startLine);
     CHECK_EQUAL(JS_GetScriptLineExtent(cx, script), 11u);
     CHECK(strcmp(JS_GetScriptFilename(script), __FILE__) == 0);
     const jschar *sourceMap = JS_GetScriptSourceMap(cx, script);
--- a/js/src/jsapi-tests/testScriptObject.cpp
+++ b/js/src/jsapi-tests/testScriptObject.cpp
@@ -13,19 +13,18 @@ struct ScriptObjectFixture : public JSAP
     static jschar uc_code[];
 
     ScriptObjectFixture()
     {
         for (int i = 0; i < code_size; i++)
             uc_code[i] = code[i];
     }
 
-    bool tryScript(JS::HandleObject global, JSScript *scriptArg)
+    bool tryScript(JS::HandleObject global, JS::HandleScript script)
     {
-        JS::RootedScript script(cx, scriptArg);
         CHECK(script);
 
         JS_GC(rt);
 
         /* After a garbage collection, the script should still work. */
         JS::RootedValue result(cx);
         CHECK(JS_ExecuteScript(cx, global, script, &result));
 
@@ -37,121 +36,136 @@ const char ScriptObjectFixture::code[] =
     "(function(a, b){return a+' '+b;}('hello', 'world'))";
 const int ScriptObjectFixture::code_size = sizeof(ScriptObjectFixture::code) - 1;
 jschar ScriptObjectFixture::uc_code[ScriptObjectFixture::code_size];
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript)
 {
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
-    return tryScript(global, JS_CompileScript(cx, global, code, code_size,
-                                              options));
+    JS::RootedScript script(cx);
+    CHECK(JS_CompileScript(cx, global, code, code_size, options, &script));
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript_empty)
 {
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
-    return tryScript(global, JS_CompileScript(cx, global, "", 0, options));
+    JS::RootedScript script(cx);
+    CHECK(JS_CompileScript(cx, global, "", 0, options, &script));
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScriptForPrincipals)
 {
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
-    return tryScript(global, JS_CompileScript(cx, global, code, code_size,
-                                              options));
+    JS::RootedScript script(cx);
+    CHECK(JS_CompileScript(cx, global, code, code_size, options, &script));
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScriptForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript)
 {
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
-    return tryScript(global, JS_CompileUCScript(cx, global, uc_code, code_size,
-                                                options));
+    JS::RootedScript script(cx);
+    CHECK(JS_CompileUCScript(cx, global, uc_code, code_size, options, &script));
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript_empty)
 {
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
-    return tryScript(global, JS_CompileUCScript(cx, global, uc_code, 0,
-                                                options));
+    JS::RootedScript script(cx);
+    CHECK(JS_CompileUCScript(cx, global, uc_code, 0, options, &script));
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScriptForPrincipals)
 {
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
-    return tryScript(global, JS_CompileUCScript(cx, global, uc_code, code_size,
-                                                options));
+    JS::RootedScript script(cx);
+    CHECK(JS_CompileUCScript(cx, global, uc_code, code_size, options, &script));
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScriptForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile)
 {
     TempFile tempScript;
     static const char script_filename[] = "temp-bug438633_JS_CompileFile";
     FILE *script_stream = tempScript.open(script_filename);
     CHECK(fputs(code, script_stream) != EOF);
     tempScript.close();
     JS::CompileOptions options(cx);
     options.setFileAndLine(script_filename, 1);
-    JSScript *script = JS::Compile(cx, global, options, script_filename);
+    JS::RootedScript script(cx);
+    CHECK(JS::Compile(cx, global, options, script_filename, &script));
     tempScript.remove();
     return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile_empty)
 {
     TempFile tempScript;
     static const char script_filename[] = "temp-bug438633_JS_CompileFile_empty";
     tempScript.open(script_filename);
     tempScript.close();
     JS::CompileOptions options(cx);
     options.setFileAndLine(script_filename, 1);
-    JSScript *script = JS::Compile(cx, global, options, script_filename);
+    JS::RootedScript script(cx);
+    CHECK(JS::Compile(cx, global, options, script_filename, &script));
     tempScript.remove();
     return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle)
 {
     const char *script_filename = "temporary file";
     TempFile tempScript;
     FILE *script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandle");
     CHECK(fputs(code, script_stream) != EOF);
     CHECK(fseek(script_stream, 0, SEEK_SET) != EOF);
     JS::CompileOptions options(cx);
     options.setFileAndLine(script_filename, 1);
-    return tryScript(global, JS::Compile(cx, global, options, script_stream));
+    JS::RootedScript script(cx);
+    CHECK(JS::Compile(cx, global, options, script_stream, &script));
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle_empty)
 {
     const char *script_filename = "empty temporary file";
     TempFile tempScript;
     FILE *script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandle_empty");
     JS::CompileOptions options(cx);
     options.setFileAndLine(script_filename, 1);
-    return tryScript(global, JS::Compile(cx, global, options, script_stream));
+    JS::RootedScript script(cx);
+    CHECK(JS::Compile(cx, global, options, script_stream, &script));
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandleForPrincipals)
 {
     TempFile tempScript;
     FILE *script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandleForPrincipals");
     CHECK(fputs(code, script_stream) != EOF);
     CHECK(fseek(script_stream, 0, SEEK_SET) != EOF);
     JS::CompileOptions options(cx);
     options.setFileAndLine("temporary file", 1);
-    return tryScript(global, JS::Compile(cx, global, options, script_stream));
+    JS::RootedScript script(cx);
+    CHECK(JS::Compile(cx, global, options, script_stream, &script));
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandleForPrincipals)
--- a/js/src/jsapi-tests/testSourcePolicy.cpp
+++ b/js/src/jsapi-tests/testSourcePolicy.cpp
@@ -12,17 +12,19 @@ BEGIN_TEST(testBug795104)
     JS::CompartmentOptionsRef(cx->compartment()).setDiscardSource(true);
     const size_t strLen = 60002;
     char *s = static_cast<char *>(JS_malloc(cx, strLen));
     CHECK(s);
     s[0] = '"';
     memset(s + 1, 'x', strLen - 2);
     s[strLen - 1] = '"';
     CHECK(JS::Evaluate(cx, global, opts, s, strLen));
-    CHECK(JS::CompileFunction(cx, global, opts, "f", 0, nullptr, s, strLen));
+    JS::RootedFunction fun(cx);
+    CHECK(JS::CompileFunction(cx, global, opts, "f", 0, nullptr, s, strLen, &fun));
+    CHECK(fun);
     JS_free(cx, s);
 
     return true;
 }
 END_TEST(testBug795104)
 
 static const char *const simpleSource = "var x = 4;";
 
--- a/js/src/jsapi-tests/testTrap.cpp
+++ b/js/src/jsapi-tests/testTrap.cpp
@@ -31,18 +31,18 @@ BEGIN_TEST(testTrap_gc)
 "    ++i;\n"
 "}\n"
 "({ result: sum });\n"
         ;
 
     // compile
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, 1);
-    JS::RootedScript script(cx, JS_CompileScript(cx, global, source,
-                                                 strlen(source), options));
+    JS::RootedScript script(cx);
+    CHECK(JS_CompileScript(cx, global, source, strlen(source), options, &script));
     CHECK(script);
 
     // execute
     JS::RootedValue v2(cx);
     CHECK(JS_ExecuteScript(cx, global, script, &v2));
     CHECK(v2.isObject());
     CHECK_EQUAL(emptyTrapCallCount, 0);
 
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -25,17 +25,18 @@ CompileScriptForPrincipalsVersionOrigin(
     jschar *chars = static_cast<jschar *>(JS_malloc(cx, nchars * sizeof(jschar)));
     if (!chars)
         return nullptr;
     JS_ALWAYS_TRUE(JS_DecodeBytes(cx, bytes, nbytes, chars, &nchars));
     JS::CompileOptions options(cx);
     options.setOriginPrincipals(originPrincipals)
            .setFileAndLine(filename, lineno)
            .setVersion(version);
-    JSScript *script = JS::Compile(cx, obj, options, chars, nchars);
+    JS::RootedScript script(cx);
+    JS::Compile(cx, obj, options, chars, nchars, &script);
     free(chars);
     return script;
 }
 
 static JSScript *
 FreezeThaw(JSContext *cx, JS::HandleScript script)
 {
     // freeze
@@ -157,18 +158,18 @@ BEGIN_TEST(testXDR_bug506491)
         "    Math.sin(value);\n"
         "    return let (n = name, v = value) function () { return String(v); };\n"
         "}\n"
         "var f = makeClosure('0;', 'status', 'ok');\n";
 
     // compile
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
-    JS::RootedScript script(cx, JS_CompileScript(cx, global, s, strlen(s),
-                                                 options));
+    JS::RootedScript script(cx);
+    CHECK(JS_CompileScript(cx, global, s, strlen(s), options, &script));
     CHECK(script);
 
     script = FreezeThaw(cx, script);
     CHECK(script);
 
     // execute
     JS::RootedValue v2(cx);
     CHECK(JS_ExecuteScript(cx, global, script, &v2));
@@ -184,17 +185,18 @@ BEGIN_TEST(testXDR_bug506491)
 }
 END_TEST(testXDR_bug506491)
 
 BEGIN_TEST(testXDR_bug516827)
 {
     // compile an empty script
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
-    JS::RootedScript script(cx, JS_CompileScript(cx, global, "", 0, options));
+    JS::RootedScript script(cx);
+    CHECK(JS_CompileScript(cx, global, "", 0, options, &script));
     CHECK(script);
 
     script = FreezeThaw(cx, script);
     CHECK(script);
 
     // execute with null result meaning no result wanted
     CHECK(JS_ExecuteScript(cx, global, script));
     return true;
@@ -207,18 +209,18 @@ BEGIN_TEST(testXDR_source)
         // This can't possibly fail to compress well, can it?
         "function f(x) { return x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x }",
         "short",
         nullptr
     };
     for (const char **s = samples; *s; s++) {
         JS::CompileOptions options(cx);
         options.setFileAndLine(__FILE__, __LINE__);
-        JS::RootedScript script(cx, JS_CompileScript(cx, global, *s, strlen(*s),
-                                                     options));
+        JS::RootedScript script(cx);
+        CHECK(JS_CompileScript(cx, global, *s, strlen(*s), options, &script));
         CHECK(script);
         script = FreezeThaw(cx, script);
         CHECK(script);
         JSString *out = JS_DecompileScript(cx, script, "testing", 0);
         CHECK(out);
         bool equal;
         CHECK(JS_StringEqualsAscii(cx, out, *s, &equal));
         CHECK(equal);
@@ -233,17 +235,17 @@ BEGIN_TEST(testXDR_sourceMap)
         "http://example.com/source-map.json",
         "file:///var/source-map.json",
         nullptr
     };
     JS::RootedScript script(cx);
     for (const char **sm = sourceMaps; *sm; sm++) {
         JS::CompileOptions options(cx);
         options.setFileAndLine(__FILE__, __LINE__);
-        script = JS_CompileScript(cx, global, "", 0, options);
+        CHECK(JS_CompileScript(cx, global, "", 0, options, &script));
         CHECK(script);
 
         size_t len = strlen(*sm);
         jschar *expected = js::InflateString(cx, *sm, &len);
         CHECK(expected);
 
         // The script source takes responsibility of free'ing |expected|.
         CHECK(script->scriptSource()->setSourceMapURL(cx, expected));
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4547,64 +4547,60 @@ JS::Compile(JSContext *cx, HandleObject 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     AutoLastFrameCheck lfc(cx);
 
     script.set(frontend::CompileScript(cx, &cx->tempLifoAlloc(), obj, NullPtr(), options, srcBuf));
     return !!script;
 }
 
-JSScript *
+bool
 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
-            const jschar *chars, size_t length)
+            const jschar *chars, size_t length, MutableHandleScript script)
 {
     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-    RootedScript script(cx);
-    if (!Compile(cx, obj, options, srcBuf, &script))
-        return nullptr;
-    return script;
-}
-
-JSScript *
+    return Compile(cx, obj, options, srcBuf, script);
+}
+
+bool
 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
-            const char *bytes, size_t length)
-{
-    jschar *chars;
+            const char *bytes, size_t length, MutableHandleScript script)
+{
+    mozilla::ScopedFreePtr<jschar> chars;
     if (options.utf8)
         chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
     else
         chars = InflateString(cx, bytes, &length);
     if (!chars)
         return nullptr;
 
-    JSScript *script = Compile(cx, obj, options, chars, length);
-    js_free(chars);
-    return script;
-}
-
-JSScript *
-JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options, FILE *fp)
+    return Compile(cx, obj, options, chars, length, script);
+}
+
+bool
+JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options, FILE *fp,
+            MutableHandleScript script)
 {
     FileContents buffer(cx);
     if (!ReadCompleteFile(cx, fp, buffer))
         return nullptr;
 
-    JSScript *script = Compile(cx, obj, options, buffer.begin(), buffer.length());
-    return script;
-}
-
-JSScript *
-JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg, const char *filename)
+    return Compile(cx, obj, options, buffer.begin(), buffer.length(), script);
+}
+
+bool
+JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg, const char *filename,
+            MutableHandleScript script)
 {
     AutoFile file;
     if (!file.open(cx, filename))
         return nullptr;
     CompileOptions options(cx, optionsArg);
     options.setFileAndLine(filename, 1);
-    return Compile(cx, obj, options, file.fp());
+    return Compile(cx, obj, options, file.fp(), script);
 }
 
 JS_PUBLIC_API(bool)
 JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length)
 {
     static const size_t TINY_LENGTH = 1000;
     static const size_t HUGE_LENGTH = 100 * 1000;
 
@@ -4648,28 +4644,28 @@ JS::FinishOffThreadScript(JSContext *may
         lfc.construct(maybecx);
 
     return HelperThreadState().finishParseTask(maybecx, rt, token);
 #else
     MOZ_ASSUME_UNREACHABLE("Off thread compilation is not available.");
 #endif
 }
 
-JS_PUBLIC_API(JSScript *)
+JS_PUBLIC_API(bool)
 JS_CompileScript(JSContext *cx, JS::HandleObject obj, const char *ascii,
-                 size_t length, const JS::CompileOptions &options)
-{
-    return Compile(cx, obj, options, ascii, length);
-}
-
-JS_PUBLIC_API(JSScript *)
+                 size_t length, const JS::CompileOptions &options, MutableHandleScript script)
+{
+    return Compile(cx, obj, options, ascii, length, script);
+}
+
+JS_PUBLIC_API(bool)
 JS_CompileUCScript(JSContext *cx, JS::HandleObject obj, const jschar *chars,
-                   size_t length, const JS::CompileOptions &options)
-{
-    return Compile(cx, obj, options, chars, length);
+                   size_t length, const JS::CompileOptions &options, MutableHandleScript script)
+{
+    return Compile(cx, obj, options, chars, length, script);
 }
 
 JS_PUBLIC_API(bool)
 JS_BufferIsCompilableUnit(JSContext *cx, HandleObject obj, const char *utf8, size_t length)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
@@ -4750,62 +4746,57 @@ JS::CompileFunction(JSContext *cx, Handl
         RootedValue value(cx, ObjectValue(*fun));
         if (!JSObject::defineGeneric(cx, obj, id, value, nullptr, nullptr, JSPROP_ENUMERATE))
             return false;
     }
 
     return true;
 }
 
-JS_PUBLIC_API(JSFunction *)
+JS_PUBLIC_API(bool)
 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
                     const char *name, unsigned nargs, const char *const *argnames,
-                    const jschar *chars, size_t length)
-{
-    RootedFunction fun(cx);
+                    const jschar *chars, size_t length, MutableHandleFunction fun)
+{
     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-    if (!JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf, &fun))
-        return nullptr;
-    return fun;
-}
-
-JS_PUBLIC_API(JSFunction *)
+    return JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf, fun);
+}
+
+JS_PUBLIC_API(bool)
 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
                     const char *name, unsigned nargs, const char *const *argnames,
-                    const char *bytes, size_t length)
-{
-    jschar *chars;
+                    const char *bytes, size_t length, MutableHandleFunction fun)
+{
+    mozilla::ScopedFreePtr<jschar> chars;
     if (options.utf8)
         chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
     else
         chars = InflateString(cx, bytes, &length);
     if (!chars)
         return nullptr;
 
-    JSFunction *fun = CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
-    js_free(chars);
-    return fun;
-}
-
-JS_PUBLIC_API(JSFunction *)
+    return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length, fun);
+}
+
+JS_PUBLIC_API(bool)
 JS_CompileUCFunction(JSContext *cx, JS::HandleObject obj, const char *name,
                      unsigned nargs, const char *const *argnames,
                      const jschar *chars, size_t length,
-                     const CompileOptions &options)
-{
-    return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
-}
-
-JS_PUBLIC_API(JSFunction *)
+                     const CompileOptions &options, MutableHandleFunction fun)
+{
+    return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length, fun);
+}
+
+JS_PUBLIC_API(bool)
 JS_CompileFunction(JSContext *cx, JS::HandleObject obj, const char *name,
                    unsigned nargs, const char *const *argnames,
                    const char *ascii, size_t length,
-                   const JS::CompileOptions &options)
-{
-    return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length);
+                   const JS::CompileOptions &options, MutableHandleFunction fun)
+{
+    return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length, fun);
 }
 
 JS_PUBLIC_API(JSString *)
 JS_DecompileScript(JSContext *cx, HandleScript script, const char *name, unsigned indent)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
 
     AssertHeapIsIdle(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3410,40 +3410,56 @@ JS_CloneFunctionObject(JSContext *cx, JS
  * true.  The intent is to support interactive compilation - accumulate
  * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
  * the compiler.
  */
 extern JS_PUBLIC_API(bool)
 JS_BufferIsCompilableUnit(JSContext *cx, JS::Handle<JSObject*> obj, const char *utf8,
                           size_t length);
 
-extern JS_PUBLIC_API(JSScript *)
+/*
+ * |script| will always be set. On failure, it will be set to nullptr.
+ */
+extern JS_PUBLIC_API(bool)
 JS_CompileScript(JSContext *cx, JS::HandleObject obj,
                  const char *ascii, size_t length,
-                 const JS::CompileOptions &options);
-
-extern JS_PUBLIC_API(JSScript *)
+                 const JS::CompileOptions &options,
+                 JS::MutableHandleScript script);
+
+/*
+ * |script| will always be set. On failure, it will be set to nullptr.
+ */
+extern JS_PUBLIC_API(bool)
 JS_CompileUCScript(JSContext *cx, JS::HandleObject obj,
                    const jschar *chars, size_t length,
-                   const JS::CompileOptions &options);
+                   const JS::CompileOptions &options,
+                   JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_GetGlobalFromScript(JSScript *script);
 
-extern JS_PUBLIC_API(JSFunction *)
+/*
+ * |fun| will always be set. On failure, it will be set to nullptr.
+ */
+extern JS_PUBLIC_API(bool)
 JS_CompileFunction(JSContext *cx, JS::HandleObject obj, const char *name,
                    unsigned nargs, const char *const *argnames,
                    const char *bytes, size_t length,
-                   const JS::CompileOptions &options);
-
-extern JS_PUBLIC_API(JSFunction *)
+                   const JS::CompileOptions &options,
+                   JS::MutableHandleFunction fun);
+
+/*
+ * |fun| will always be set. On failure, it will be set to nullptr.
+ */
+extern JS_PUBLIC_API(bool)
 JS_CompileUCFunction(JSContext *cx, JS::HandleObject obj, const char *name,
                      unsigned nargs, const char *const *argnames,
                      const jschar *chars, size_t length,
-                     const JS::CompileOptions &options);
+                     const JS::CompileOptions &options,
+                     JS::MutableHandleFunction fun);
 
 namespace JS {
 
 /* Options for JavaScript compilation. */
 
 /*
  * In the most common use case, a CompileOptions instance is allocated on the
  * stack, and holds non-owning references to non-POD option values: strings;
@@ -3762,29 +3778,31 @@ class MOZ_STACK_CLASS JS_FRIEND_API(Comp
 
 /*
  * |script| will always be set. On failure, it will be set to nullptr.
  */
 extern JS_PUBLIC_API(bool)
 Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
         SourceBufferHolder &srcBuf, JS::MutableHandleScript script);
 
-extern JS_PUBLIC_API(JSScript *)
+extern JS_PUBLIC_API(bool)
 Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
-        const char *bytes, size_t length);
-
-extern JS_PUBLIC_API(JSScript *)
+        const char *bytes, size_t length, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
 Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
-        const jschar *chars, size_t length);
-
-extern JS_PUBLIC_API(JSScript *)
-Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, FILE *file);
-
-extern JS_PUBLIC_API(JSScript *)
-Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, const char *filename);
+        const jschar *chars, size_t length, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, FILE *file,
+        JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, const char *filename,
+        JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length);
 
 /*
  * Off thread compilation control flow.
  *
  * After successfully triggering an off thread compile of a script, the
@@ -3808,25 +3826,25 @@ CompileOffThread(JSContext *cx, const Re
 extern JS_PUBLIC_API(JSScript *)
 FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token);
 
 extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
                 SourceBufferHolder &srcBuf, JS::MutableHandleFunction fun);
 
-extern JS_PUBLIC_API(JSFunction *)
+extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
-                const char *bytes, size_t length);
-
-extern JS_PUBLIC_API(JSFunction *)
+                const char *bytes, size_t length, JS::MutableHandleFunction fun);
+
+extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
-                const jschar *chars, size_t length);
+                const jschar *chars, size_t length, JS::MutableHandleFunction fun);
 
 } /* namespace JS */
 
 extern JS_PUBLIC_API(JSString *)
 JS_DecompileScript(JSContext *cx, JS::Handle<JSScript*> script, const char *name, unsigned indent);
 
 /*
  * API extension: OR this into indent to avoid pretty-printing the decompiled
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -431,17 +431,17 @@ RunFile(JSContext *cx, Handle<JSObject*>
 
         CompileOptions options(cx);
         options.setIntroductionType("js shell file")
                .setUTF8(true)
                .setFileAndLine(filename, 1)
                .setCompileAndGo(true);
 
         gGotError = false;
-        script = JS::Compile(cx, obj, options, file);
+        (void) JS::Compile(cx, obj, options, file, &script);
         JS_ASSERT_IF(!script, gGotError);
     }
 
     #ifdef DEBUG
         if (dumpEntrainedVariables)
             AnalyzeEntrainedVariables(cx, script);
     #endif
     if (script && !compileOnly) {
@@ -461,18 +461,17 @@ EvalAndPrint(JSContext *cx, Handle<JSObj
 {
     // Eval.
     JS::CompileOptions options(cx);
     options.setIntroductionType("js shell interactive")
            .setUTF8(true)
            .setCompileAndGo(true)
            .setFileAndLine("typein", lineno);
     RootedScript script(cx);
-    script = JS::Compile(cx, global, options, bytes, length);
-    if (!script)
+    if (!JS::Compile(cx, global, options, bytes, length, &script))
         return false;
     if (compileOnly)
         return true;
     RootedValue result(cx);
     if (!JS_ExecuteScript(cx, global, script, &result))
         return false;
 
     if (!result.isUndefined()) {
@@ -850,17 +849,18 @@ LoadScript(JSContext *cx, unsigned argc,
         if (!filename)
             return false;
         errno = 0;
         CompileOptions opts(cx);
         opts.setIntroductionType("js shell load")
             .setUTF8(true)
             .setCompileAndGo(true)
             .setNoScriptRval(true);
-        if ((compileOnly && !Compile(cx, thisobj, opts, filename.ptr())) ||
+        RootedScript script(cx);
+        if ((compileOnly && !Compile(cx, thisobj, opts, filename.ptr(), &script)) ||
             !Evaluate(cx, thisobj, opts, filename.ptr()))
         {
             return false;
         }
     }
 
     args.rval().setUndefined();
     return true;
@@ -1263,17 +1263,17 @@ Evaluate(JSContext *cx, unsigned argc, j
                 }
                 JS::CompartmentOptionsRef(cx).cloneSingletonsOverride().set(true);
             }
 
             if (loadBytecode) {
                 script = JS_DecodeScript(cx, loadBuffer, loadLength, options.originPrincipals(cx));
             } else {
                 mozilla::Range<const jschar> chars = codeChars.twoByteRange();
-                script = JS::Compile(cx, global, options, chars.start().get(), chars.length());
+                (void) JS::Compile(cx, global, options, chars.start().get(), chars.length(), &script);
             }
 
             if (!script)
                 return false;
         }
 
         if (displayURL && !script->scriptSource()->hasDisplayURL()) {
             JSFlatString *flat = displayURL->ensureFlat(cx);
@@ -1466,18 +1466,17 @@ Run(JSContext *cx, unsigned argc, jsval 
     {
         JS::AutoSaveContextOptions asco(cx);
         JS::ContextOptionsRef(cx).setNoScriptRval(true);
 
         JS::CompileOptions options(cx);
         options.setIntroductionType("js shell run")
                .setFileAndLine(filename.ptr(), 1)
                .setCompileAndGo(true);
-        script = JS_CompileUCScript(cx, thisobj, ucbuf, buflen, options);
-        if (!script)
+        if (!JS_CompileUCScript(cx, thisobj, ucbuf, buflen, options, &script))
             return false;
     }
 
     if (!JS_ExecuteScript(cx, thisobj, script))
         return false;
 
     int64_t endClock = PRMJ_Now();
 
@@ -2313,18 +2312,17 @@ DisassFile(JSContext *cx, unsigned argc,
         JS::ContextOptionsRef(cx).setNoScriptRval(true);
 
         CompileOptions options(cx);
         options.setIntroductionType("js shell disFile")
                .setUTF8(true)
                .setFileAndLine(filename.ptr(), 1)
                .setCompileAndGo(true);
 
-        script = JS::Compile(cx, thisobj, options, filename.ptr());
-        if (!script)
+        if (!JS::Compile(cx, thisobj, options, filename.ptr(), &script))
             return false;
     }
 
     Sprinter sprinter(cx);
     if (!sprinter.init())
         return false;
     bool ok = DisassembleScript(cx, script, NullPtr(), p.lines, p.recursive, &sprinter);
     if (ok)
@@ -2919,19 +2917,18 @@ WorkerMain(void *arg)
             break;
 
         JSAutoCompartment ac(cx, global);
 
         JS::CompileOptions options(cx);
         options.setFileAndLine("<string>", 1)
                .setCompileAndGo(true);
 
-        RootedScript script(cx, JS::Compile(cx, global, options,
-                                            input->chars, input->length));
-        if (!script)
+        RootedScript script(cx);
+        if (!JS::Compile(cx, global, options, input->chars, input->length, &script))
             break;
         RootedValue result(cx);
         JS_ExecuteScript(cx, global, script, &result);
     } while (0);
 
     DestroyContext(cx, false);
     JS_DestroyRuntime(rt);
 
@@ -3554,20 +3551,20 @@ Compile(JSContext *cx, unsigned argc, js
         return false;
 
     JS::AutoSaveContextOptions asco(cx);
     JS::ContextOptionsRef(cx).setNoScriptRval(true);
     JS::CompileOptions options(cx);
     options.setIntroductionType("js shell compile")
            .setFileAndLine("<string>", 1)
            .setCompileAndGo(true);
-
+    RootedScript script(cx);
     const jschar *chars = stableChars.twoByteRange().start().get();
     bool ok = JS_CompileUCScript(cx, global, chars,
-                                 scriptContents->length(), options);
+                                 scriptContents->length(), options, &script);
     args.rval().setUndefined();
     return ok;
 }
 
 static bool
 Parse(JSContext *cx, unsigned argc, jsval *vp)
 {
     using namespace js::frontend;
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -1005,18 +1005,18 @@ JSRuntime::initSelfHosting(JSContext *cx
      * and we don't want errors in self-hosted code to be silently swallowed.
      */
     JSErrorReporter oldReporter = JS_SetErrorReporter(cx, selfHosting_ErrorReporter);
     RootedValue rv(cx);
     bool ok = false;
 
     char *filename = getenv("MOZ_SELFHOSTEDJS");
     if (filename) {
-        RootedScript script(cx, Compile(cx, shg, options, filename));
-        if (script)
+        RootedScript script(cx);
+        if (Compile(cx, shg, options, filename, &script))
             ok = Execute(cx, script, *shg.get(), rv.address());
     } else {
         uint32_t srcLen = GetRawScriptsSize();
 
 #ifdef USE_ZLIB
         const unsigned char *compressed = compressedSources;
         uint32_t compressedLen = GetCompressedSize();
         ScopedJSFreePtr<char> src(reinterpret_cast<char *>(cx->malloc_(srcLen)));
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -896,22 +896,21 @@ mozJSComponentLoader::ObjectForLocation(
 
             char *buf = static_cast<char*>(PR_MemMap(map, 0, fileSize32));
             if (!buf) {
                 NS_WARNING("Failed to map file");
                 return NS_ERROR_FAILURE;
             }
 
             if (!mReuseLoaderGlobal) {
-                script = Compile(cx, obj, options, buf,
-                                     fileSize32);
+                Compile(cx, obj, options, buf, fileSize32, &script);
             } else {
-                function = CompileFunction(cx, obj, options,
-                                               nullptr, 0, nullptr,
-                                               buf, fileSize32);
+                CompileFunction(cx, obj, options,
+                                nullptr, 0, nullptr,
+                                buf, fileSize32, &function);
             }
 
             PR_MemUnmap(buf, fileSize32);
 
 #else  /* HAVE_PR_MEMMAP */
 
             /**
              * No memmap implementation, so fall back to
@@ -983,21 +982,21 @@ mozJSComponentLoader::ObjectForLocation(
             /* read the file in one swoop */
             rv = scriptStream->Read(buf, len, &bytesRead);
             if (bytesRead != len)
                 return NS_BASE_STREAM_OSERROR;
 
             buf[len] = '\0';
 
             if (!mReuseLoaderGlobal) {
-                script = Compile(cx, obj, options, buf, bytesRead);
+                Compile(cx, obj, options, buf, bytesRead, &script);
             } else {
-                function = CompileFunction(cx, obj, options,
-                                               nullptr, 0, nullptr,
-                                               buf, bytesRead);
+                CompileFunction(cx, obj, options,
+                                nullptr, 0, nullptr,
+                                buf, bytesRead, &function);
             }
         }
         // Propagate the exception, if one exists. Also, don't leave the stale
         // exception on this context.
         if (!script && !function && aPropagateExceptions) {
             JS_GetPendingException(cx, aException);
             JS_ClearPendingException(cx);
         }
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -162,21 +162,21 @@ mozJSSubScriptLoader::ReadScript(nsIURI 
                                 srcBuf,
                                 function);
         }
     } else {
         // We only use lazy source when no special encoding is specified because
         // the lazy source loader doesn't know the encoding.
         if (!reuseGlobal) {
             options.setSourceIsLazy(true);
-            script.set(JS::Compile(cx, target_obj, options, buf.get(), len));
+            JS::Compile(cx, target_obj, options, buf.get(), len, script);
         } else {
-            function.set(JS::CompileFunction(cx, target_obj, options,
-                                             nullptr, 0, nullptr, buf.get(),
-                                             len));
+            JS::CompileFunction(cx, target_obj, options,
+                                nullptr, 0, nullptr, buf.get(),
+                                len, function);
         }
     }
 
     /* repent for our evil deeds */
     JS_SetErrorReporter(cx, er);
 
     return NS_OK;
 }
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -335,17 +335,18 @@ Load(JSContext *cx, unsigned argc, jsval
         if (!file) {
             JS_ReportError(cx, "cannot open file '%s' for reading",
                            filename.ptr());
             return false;
         }
         JS::CompileOptions options(cx);
         options.setUTF8(true)
                .setFileAndLine(filename.ptr(), 1);
-        JS::Rooted<JSScript*> script(cx, JS::Compile(cx, obj, options, file));
+        JS::Rooted<JSScript*> script(cx);
+        JS::Compile(cx, obj, options, file, &script);
         fclose(file);
         if (!script)
             return false;
 
         if (!compileOnly && !JS_ExecuteScript(cx, obj, script))
             return false;
     }
     args.rval().setUndefined();
@@ -919,18 +920,17 @@ ProcessFile(JSContext *cx, JS::Handle<JS
             }
         }
         ungetc(ch, file);
         DoBeginRequest(cx);
 
         JS::CompileOptions options(cx);
         options.setUTF8(true)
                .setFileAndLine(filename, 1);
-        script = JS::Compile(cx, obj, options, file);
-        if (script && !compileOnly)
+        if (JS::Compile(cx, obj, options, file, &script) && !compileOnly)
             (void)JS_ExecuteScript(cx, obj, script, &result);
         DoEndRequest(cx);
 
         return;
     }
 
     /* It's an interactive filehandle; drop into read-eval-print loop. */
     lineno = 1;
@@ -955,18 +955,17 @@ ProcessFile(JSContext *cx, JS::Handle<JS
             lineno++;
         } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
 
         DoBeginRequest(cx);
         /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
         JS::CompileOptions options(cx);
         options.setFileAndLine("typein", startline);
-        script = JS_CompileScript(cx, obj, buffer, strlen(buffer), options);
-        if (script) {
+        if (JS_CompileScript(cx, obj, buffer, strlen(buffer), options, &script)) {
             JSErrorReporter older;
 
             if (!compileOnly) {
                 ok = JS_ExecuteScript(cx, obj, script, &result);
                 if (ok && result != JSVAL_VOID) {
                     /* Suppress error reports from JS::ToString(). */
                     older = JS_SetErrorReporter(cx, nullptr);
                     str = ToString(cx, result);
--- a/netwerk/base/src/ProxyAutoConfig.cpp
+++ b/netwerk/base/src/ProxyAutoConfig.cpp
@@ -632,19 +632,21 @@ ProxyAutoConfig::SetupJS()
   // huge meaningless strings. this is not on the main thread, so it can't
   // use nsIRUI scheme methods
   bool isDataURI = nsDependentCSubstring(mPACURI, 0, 5).LowerCaseEqualsASCII("data:", 5);
 
   sRunning = this;
   JS::Rooted<JSObject*> global(cx, mJSRuntime->Global());
   JS::CompileOptions options(cx);
   options.setFileAndLine(mPACURI.get(), 1);
-  JS::Rooted<JSScript*> script(cx, JS_CompileScript(cx, global, mPACScript.get(),
-                                                    mPACScript.Length(), options));
-  if (!script || !JS_ExecuteScript(cx, global, script)) {
+  JS::Rooted<JSScript*> script(cx);
+  if (!JS_CompileScript(cx, global, mPACScript.get(),
+                        mPACScript.Length(), options, &script) ||
+      !JS_ExecuteScript(cx, global, script))
+  {
     nsString alertMessage(NS_LITERAL_STRING("PAC file failed to install from "));
     if (isDataURI) {
       alertMessage += NS_LITERAL_STRING("data: URI");
     }
     else {
       alertMessage += NS_ConvertUTF8toUTF16(mPACURI);
     }
     PACLogToConsole(alertMessage);