Bug 1542910 - Make all script compilation APIs directly return a JSScript*, rather than returning a success code and returning the JSScript* via outparam that exactly duplicates the success code value's meaning. r=arai
authorJeff Walden <jwalden@mit.edu>
Tue, 09 Apr 2019 17:58:52 +0000
changeset 468605 5c5765ae3e648c812c09e86b76ca59d297363cb2
parent 468604 6a948ab124ae27dc4f66bd7059505ae11b096fc4
child 468606 e05177437976417d180e1173ef99e3c17079ca34
push id35843
push usernbeleuzu@mozilla.com
push dateTue, 09 Apr 2019 22:08:13 +0000
treeherdermozilla-central@a31032a16330 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1542910
milestone68.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 1542910 - Make all script compilation APIs directly return a JSScript*, rather than returning a success code and returning the JSScript* via outparam that exactly duplicates the success code value's meaning. r=arai Differential Revision: https://phabricator.services.mozilla.com/D26616
dom/base/nsFrameMessageManager.cpp
dom/base/nsJSUtils.cpp
dom/xul/nsXULElement.cpp
ipc/testshell/XPCShellEnvironment.cpp
js/public/CompilationAndEvaluation.h
js/src/builtin/TestingFunctions.cpp
js/src/jsapi-tests/testCompileNonSyntactic.cpp
js/src/jsapi-tests/testCompileUtf8.cpp
js/src/jsapi-tests/testEmptyWindowIsOmitted.cpp
js/src/jsapi-tests/testExecuteInJSMEnvironment.cpp
js/src/jsapi-tests/testGCCellPtr.cpp
js/src/jsapi-tests/testPrivateGCThingValue.cpp
js/src/jsapi-tests/testScriptInfo.cpp
js/src/jsapi-tests/testScriptObject.cpp
js/src/jsapi-tests/testUbiNode.cpp
js/src/jsapi-tests/testXDR.cpp
js/src/shell/js.cpp
js/src/vm/CompilationAndEvaluation.cpp
js/xpconnect/loader/ChromeScriptLoader.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.h
js/xpconnect/src/XPCShellImpl.cpp
netwerk/base/ProxyAutoConfig.cpp
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -1314,17 +1314,18 @@ void nsMessageManagerScriptExecutor::Try
     if (!srcBuf.init(cx, std::move(srcChars), dataStringLength)) {
       return;
     }
 
     JS::CompileOptions options(cx);
     options.setFileAndLine(url.get(), 1);
     options.setNoScriptRval(true);
 
-    if (!JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script)) {
+    script = JS::CompileForNonSyntacticScope(cx, options, srcBuf);
+    if (!script) {
       return;
     }
   }
 
   MOZ_ASSERT(script);
   aScriptp.set(script);
 
   nsAutoCString scheme;
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -211,26 +211,22 @@ nsresult nsJSUtils::ExecutionContext::Co
 
   MOZ_ASSERT(aSrcBuf.get());
   MOZ_ASSERT(mRetValue.isUndefined());
 #ifdef DEBUG
   mWantsReturnValue = !aCompileOptions.noScriptRval;
 #endif
 
   MOZ_ASSERT(!mScript);
-  bool compiled = true;
-  if (mScopeChain.length() == 0) {
-    compiled = JS::Compile(mCx, aCompileOptions, aSrcBuf, &mScript);
-  } else {
-    compiled = JS::CompileForNonSyntacticScope(mCx, aCompileOptions, aSrcBuf,
-                                               &mScript);
-  }
+  mScript =
+      mScopeChain.length() == 0
+          ? JS::Compile(mCx, aCompileOptions, aSrcBuf)
+          : JS::CompileForNonSyntacticScope(mCx, aCompileOptions, aSrcBuf);
 
-  MOZ_ASSERT_IF(compiled, mScript);
-  if (!compiled) {
+  if (!mScript) {
     mSkip = true;
     mRv = EvaluationExceptionToNSResult(mCx);
     return mRv;
   }
 
   if (mEncodeBytecode && !StartIncrementalEncoding(mCx, mScript)) {
     mSkip = true;
     mRv = EvaluationExceptionToNSResult(mCx);
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -2142,19 +2142,20 @@ nsresult nsXULPrototypeScript::Compile(
   if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options, aTextLength)) {
     if (!JS::CompileOffThread(cx, options, srcBuf,
                               OffThreadScriptReceiverCallback,
                               static_cast<void*>(aOffThreadReceiver))) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     NotifyOffThreadScriptCompletedRunnable::NoteReceiver(aOffThreadReceiver);
   } else {
-    JS::Rooted<JSScript*> script(cx);
-    if (!JS::Compile(cx, options, srcBuf, &script))
+    JS::Rooted<JSScript*> script(cx, JS::Compile(cx, options, srcBuf));
+    if (!script) {
       return NS_ERROR_OUT_OF_MEMORY;
+    }
     Set(script);
   }
   return NS_OK;
 }
 
 void nsXULPrototypeScript::UnlinkJSObjects() {
   if (mScriptObject) {
     mScriptObject = nullptr;
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -134,20 +134,19 @@ static bool Load(JSContext *cx, unsigned
       JS_ReportErrorUTF8(cx, "cannot open file '%s' for reading",
                          filename.get());
       return false;
     }
 
     JS::CompileOptions options(cx);
     options.setFileAndLine(filename.get(), 1);
 
-    JS::Rooted<JSScript *> script(cx);
-    bool ok = JS::CompileUtf8File(cx, options, file, &script);
+    JS::Rooted<JSScript *> script(cx, JS::CompileUtf8File(cx, options, file));
     fclose(file);
-    if (!ok) return false;
+    if (!script) return false;
 
     if (!JS_ExecuteScript(cx, script)) {
       return false;
     }
   }
   args.rval().setUndefined();
   return true;
 }
@@ -246,19 +245,20 @@ void XPCShellEnvironment::ProcessFile(JS
         if (ch == '\n' || ch == '\r') break;
       }
     }
     ungetc(ch, file);
 
     JS::CompileOptions options(cx);
     options.setFileAndLine(filename, 1);
 
-    JS::Rooted<JSScript *> script(cx);
-    if (JS::CompileUtf8File(cx, options, file, &script))
+    JS::Rooted<JSScript *> script(cx, JS::CompileUtf8File(cx, options, file));
+    if (script) {
       (void)JS_ExecuteScript(cx, script, &result);
+    }
 
     return;
   }
 
   /* It's an interactive filehandle; drop into read-eval-print loop. */
   lineno = 1;
   hitEOF = false;
   do {
@@ -283,18 +283,19 @@ void XPCShellEnvironment::ProcessFile(JS
         !JS_Utf8BufferIsCompilableUnit(cx, global, 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);
-    if (JS::CompileUtf8(cx, options, buffer, strlen(buffer), &script)) {
+    JS::Rooted<JSScript *> script(
+        cx, JS::CompileUtf8(cx, options, buffer, strlen(buffer)));
+    if (script) {
       ok = JS_ExecuteScript(cx, script, &result);
       if (ok && !result.isUndefined()) {
         /* Suppress warnings from JS::ToString(). */
         JS::AutoSuppressWarningReporter suppressWarnings(cx);
         str = JS::ToString(cx, result);
         JS::UniqueChars bytes;
         if (str) bytes = JS_EncodeStringToLatin1(cx, str);
 
@@ -420,18 +421,18 @@ bool XPCShellEnvironment::EvaluateString
   options.setFileAndLine("typein", 0);
 
   JS::SourceText<char16_t> srcBuf;
   if (!srcBuf.init(cx, aString.get(), aString.Length(),
                    JS::SourceOwnership::Borrowed)) {
     return false;
   }
 
-  JS::Rooted<JSScript *> script(cx);
-  if (!JS::Compile(cx, options, srcBuf, &script)) {
+  JS::Rooted<JSScript *> script(cx, JS::Compile(cx, options, srcBuf));
+  if (!script) {
     return false;
   }
 
   if (aResult) {
     aResult->Truncate();
   }
 
   JS::Rooted<JS::Value> result(cx);
--- a/js/public/CompilationAndEvaluation.h
+++ b/js/public/CompilationAndEvaluation.h
@@ -142,112 +142,101 @@ extern JS_PUBLIC_API bool EvaluateUtf8(J
  * [necessarily] UTF-8.)  If the contents contain any malformed UTF-8, an error
  * is reported.
  */
 extern JS_PUBLIC_API bool EvaluateUtf8Path(
     JSContext* cx, const ReadOnlyCompileOptions& options, const char* filename,
     MutableHandle<Value> rval);
 
 /**
- * |script| will always be set. On failure, it will be set to nullptr.
+ * Compile the provided script using the given options.  Return the script on
+ * success, or return null on failure (usually with an error reported).
  */
-extern JS_PUBLIC_API bool Compile(JSContext* cx,
-                                  const ReadOnlyCompileOptions& options,
-                                  SourceText<char16_t>& srcBuf,
-                                  MutableHandle<JSScript*> script);
+extern JS_PUBLIC_API JSScript* Compile(JSContext* cx,
+                                       const ReadOnlyCompileOptions& options,
+                                       SourceText<char16_t>& srcBuf);
 
 /**
  * Identical to |JS::Compile|, but compiles UTF-8.
  *
  * The "DontInflate" suffix is temporary while bugs in UTF-8 compilation are
  * ironed out.  In the long term this function and |JS::Compile| will follow
  * the same naming scheme.
  *
  * NOTE: This function DOES NOT INFLATE the UTF-8 bytes to UTF-16 before
  *       compiling them.  UTF-8 compilation is currently experimental and has
  *       known bugs.  Use only if you're willing to tolerate unspecified bugs!
  */
-extern JS_PUBLIC_API bool CompileDontInflate(
+extern JS_PUBLIC_API JSScript* CompileDontInflate(
     JSContext* cx, const ReadOnlyCompileOptions& options,
-    SourceText<mozilla::Utf8Unit>& srcBuf, MutableHandle<JSScript*> script);
+    SourceText<mozilla::Utf8Unit>& srcBuf);
 
 /**
- * Compile the provided UTF-8 data into a script.  If the data contains invalid
- * UTF-8, an error is reported.
- *
- * |script| is always set to the compiled script or to null in case of error.
+ * Compile the provided UTF-8 data into a script.  It is an error if the data
+ * contains invalid UTF-8.  Return the script on success, or return null on
+ * failure (usually with an error reported).
  */
-extern JS_PUBLIC_API bool CompileUtf8(JSContext* cx,
-                                      const ReadOnlyCompileOptions& options,
-                                      const char* bytes, size_t length,
-                                      MutableHandle<JSScript*> script);
+extern JS_PUBLIC_API JSScript* CompileUtf8(
+    JSContext* cx, const ReadOnlyCompileOptions& options, const char* bytes,
+    size_t length);
 
 /**
- * Compile the provided UTF-8 data into a script.  If the data contains invalid
- * UTF-8, an error is reported.
- *
- * |script| is always set to the compiled script or to null in case of error.
+ * Compile the provided UTF-8 data into a script.  It is an error if the data
+ * contains invalid UTF-8.  Return the script on success, or return null on
+ * failure (usually with an error reported).
  *
  * NOTE: This function DOES NOT INFLATE the UTF-8 bytes to UTF-16 before
  *       compiling them.  UTF-8 compilation is currently experimental and has
  *       known bugs.  Use only if you're willing to tolerate unspecified bugs!
  */
-extern JS_PUBLIC_API bool CompileUtf8DontInflate(
+extern JS_PUBLIC_API JSScript* CompileUtf8DontInflate(
     JSContext* cx, const ReadOnlyCompileOptions& options, const char* bytes,
-    size_t length, MutableHandle<JSScript*> script);
+    size_t length);
 
 /**
- * Compile the UTF-8 contents of the given file into a script.  If the contents
- * contain any malformed UTF-8, an error is reported.
- *
- * |script| is always set to the compiled script or to null in case of error.
+ * Compile the UTF-8 contents of the given file into a script.  It is an error
+ * if the file contains invalid UTF-8.  Return the script on success, or return
+ * null on failure (usually with an error reported).
  */
-extern JS_PUBLIC_API bool CompileUtf8File(JSContext* cx,
-                                          const ReadOnlyCompileOptions& options,
-                                          FILE* file,
-                                          MutableHandle<JSScript*> script);
+extern JS_PUBLIC_API JSScript* CompileUtf8File(
+    JSContext* cx, const ReadOnlyCompileOptions& options, FILE* file);
 
 /**
- * Compile the UTF-8 contents of the given file into a script.  If the contents
- * contain any malformed UTF-8, an error is reported.
- *
- * |script| is always set to the compiled script or to null in case of error.
+ * Compile the UTF-8 contents of the given file into a script.  It is an error
+ * if the file contains invalid UTF-8.  Return the script on success, or return
+ * null on failure (usually with an error reported).
  *
  * NOTE: This function DOES NOT INFLATE the UTF-8 bytes to UTF-16 before
  *       compiling them.  UTF-8 compilation is currently experimental and has
  *       known bugs.  Use only if you're willing to tolerate unspecified bugs!
  */
-extern JS_PUBLIC_API bool CompileUtf8FileDontInflate(
-    JSContext* cx, const ReadOnlyCompileOptions& options, FILE* file,
-    MutableHandle<JSScript*> script);
+extern JS_PUBLIC_API JSScript* CompileUtf8FileDontInflate(
+    JSContext* cx, const ReadOnlyCompileOptions& options, FILE* file);
 
 /**
  * Compile the UTF-8 contents of the file at the given path into a script.
- * (The path itself is in the system encoding, not [necessarily] UTF-8.)  If
- * the contents contain any malformed UTF-8, an error is reported.
- *
- * |script| is always set to the compiled script or to null in case of error.
+ * (The path itself is in the system encoding, not [necessarily] UTF-8.)  It
+ * is an error if the file's contents are invalid UTF-8.  Return the script on
+ * success, or return null on failure (usually with an error reported).
  */
-extern JS_PUBLIC_API bool CompileUtf8Path(JSContext* cx,
-                                          const ReadOnlyCompileOptions& options,
-                                          const char* filename,
-                                          MutableHandle<JSScript*> script);
+extern JS_PUBLIC_API JSScript* CompileUtf8Path(
+    JSContext* cx, const ReadOnlyCompileOptions& options, const char* filename);
 
-extern JS_PUBLIC_API bool CompileForNonSyntacticScope(
+extern JS_PUBLIC_API JSScript* CompileForNonSyntacticScope(
     JSContext* cx, const ReadOnlyCompileOptions& options,
-    SourceText<char16_t>& srcBuf, MutableHandle<JSScript*> script);
+    SourceText<char16_t>& srcBuf);
 
 /**
- * Compile the given UTF-8 data for non-syntactic scope.
- *
- * An exception is thrown if the data isn't valid UTF-8.
+ * Compile the provided UTF-8 data into a script in a non-syntactic scope.  It
+ * is an error if the data contains invalid UTF-8.  Return the script on
+ * success, or return null on failure (usually with an error reported).
  */
-extern JS_PUBLIC_API bool CompileUtf8ForNonSyntacticScope(
+extern JS_PUBLIC_API JSScript* CompileUtf8ForNonSyntacticScope(
     JSContext* cx, const ReadOnlyCompileOptions& options, const char* bytes,
-    size_t length, MutableHandle<JSScript*> script);
+    size_t length);
 
 /**
  * Compile a function with envChain plus the global as its scope chain.
  * envChain must contain objects in the current compartment of cx.  The actual
  * scope chain used for the function will consist of With wrappers for those
  * objects, followed by the current global of the compartment cx is in.  This
  * global must not be explicitly included in the scope chain.
  */
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -3903,18 +3903,18 @@ static bool EvalReturningScope(JSContext
   options.setFileAndLine(filename.get(), lineno);
   options.setNoScriptRval(true);
 
   JS::SourceText<char16_t> srcBuf;
   if (!srcBuf.init(cx, src, srclen, SourceOwnership::Borrowed)) {
     return false;
   }
 
-  RootedScript script(cx);
-  if (!JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script)) {
+  RootedScript script(cx, JS::CompileForNonSyntacticScope(cx, options, srcBuf));
+  if (!script) {
     return false;
   }
 
   if (global) {
     global = CheckedUnwrapDynamic(global, cx);
     if (!global) {
       JS_ReportErrorASCII(cx, "Permission denied to access global");
       return false;
@@ -4007,18 +4007,18 @@ static bool ShellCloneAndExecuteScript(J
   options.setFileAndLine(filename.get(), lineno);
   options.setNoScriptRval(true);
 
   JS::SourceText<char16_t> srcBuf;
   if (!srcBuf.init(cx, src, srclen, SourceOwnership::Borrowed)) {
     return false;
   }
 
-  RootedScript script(cx);
-  if (!JS::Compile(cx, options, srcBuf, &script)) {
+  RootedScript script(cx, JS::Compile(cx, options, srcBuf));
+  if (!script) {
     return false;
   }
 
   global = CheckedUnwrapDynamic(global, cx);
   if (!global) {
     JS_ReportErrorASCII(cx, "Permission denied to access global");
     return false;
   }
@@ -5426,22 +5426,18 @@ JSScript* js::TestingFunctionArgumentToS
     }
     const char16_t* chars = linearChars.twoByteRange().begin().get();
 
     SourceText<char16_t> source;
     if (!source.init(cx, chars, len, SourceOwnership::Borrowed)) {
       return nullptr;
     }
 
-    RootedScript script(cx);
     CompileOptions options(cx);
-    if (!JS::Compile(cx, options, source, &script)) {
-      return nullptr;
-    }
-    return script;
+    return JS::Compile(cx, options, source);
   }
 
   RootedFunction fun(cx, JS_ValueToFunction(cx, v));
   if (!fun) {
     return nullptr;
   }
 
   // Unwrap bound functions.
--- a/js/src/jsapi-tests/testCompileNonSyntactic.cpp
+++ b/js/src/jsapi-tests/testCompileNonSyntactic.cpp
@@ -64,41 +64,47 @@ bool testCompile(bool nonSyntactic) {
 
   JS::SourceText<char16_t> buf;
   CHECK(buf.init(cx, src_16, length, JS::SourceOwnership::Borrowed));
 
   JS::RootedScript script(cx);
 
   // Check explicit non-syntactic compilation first to make sure it doesn't
   // modify our options object.
-  CHECK(CompileForNonSyntacticScope(cx, options, buf, &script));
+  script = CompileForNonSyntacticScope(cx, options, buf);
+  CHECK(script);
   CHECK_EQUAL(script->hasNonSyntacticScope(), true);
 
-  CHECK(CompileUtf8ForNonSyntacticScope(cx, options, src, length, &script));
+  script = CompileUtf8ForNonSyntacticScope(cx, options, src, length);
+  CHECK(script);
   CHECK_EQUAL(script->hasNonSyntacticScope(), true);
 
   {
     JS::SourceText<char16_t> srcBuf;
     CHECK(srcBuf.init(cx, src_16, length, JS::SourceOwnership::Borrowed));
 
-    CHECK(CompileForNonSyntacticScope(cx, options, srcBuf, &script));
+    script = CompileForNonSyntacticScope(cx, options, srcBuf);
+    CHECK(script);
     CHECK_EQUAL(script->hasNonSyntacticScope(), true);
   }
 
-  CHECK(Compile(cx, options, buf, &script));
+  script = Compile(cx, options, buf);
+  CHECK(script);
   CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
 
-  CHECK(CompileUtf8(cx, options, src, length, &script));
+  script = CompileUtf8(cx, options, src, length);
+  CHECK(script);
   CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
 
   {
     JS::SourceText<char16_t> srcBuf;
     CHECK(srcBuf.init(cx, src_16, length, JS::SourceOwnership::Borrowed));
 
-    CHECK(Compile(cx, options, srcBuf, &script));
+    script = Compile(cx, options, srcBuf);
+    CHECK(script);
     CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
   }
 
   options.forceAsync = true;
   OffThreadTask task;
   OffThreadToken* token;
 
   JS::SourceText<char16_t> srcBuf;
--- a/js/src/jsapi-tests/testCompileUtf8.cpp
+++ b/js/src/jsapi-tests/testCompileUtf8.cpp
@@ -181,17 +181,18 @@ static bool isNotShortestFormMessage(con
 }
 
 template <size_t N, typename TestMessage>
 bool testBadUtf8(const char (&chars)[N], unsigned errorNumber,
                  TestMessage testMessage, const char* badBytes) {
   JS::Rooted<JSScript*> script(cx);
   {
     JS::CompileOptions options(cx);
-    CHECK(!JS::CompileUtf8DontInflate(cx, options, chars, N - 1, &script));
+    script = JS::CompileUtf8DontInflate(cx, options, chars, N - 1);
+    CHECK(!script);
   }
 
   JS::RootedValue exn(cx);
   CHECK(JS_GetPendingException(cx, &exn));
   JS_ClearPendingException(cx);
 
   js::ErrorReport report(cx);
   CHECK(report.init(cx, exn, js::ErrorReport::WithSideEffects));
@@ -260,17 +261,18 @@ BEGIN_TEST(testMultiUnitUtf8InWindow) {
 }
 
 template <size_t N, size_t ContextLenWithNull>
 bool testContext(const char (&chars)[N],
                  const char16_t (&expectedContext)[ContextLenWithNull]) {
   JS::Rooted<JSScript*> script(cx);
   {
     JS::CompileOptions options(cx);
-    CHECK(!JS::CompileUtf8DontInflate(cx, options, chars, N - 1, &script));
+    script = JS::CompileUtf8DontInflate(cx, options, chars, N - 1);
+    CHECK(!script);
   }
 
   JS::RootedValue exn(cx);
   CHECK(JS_GetPendingException(cx, &exn));
   JS_ClearPendingException(cx);
 
   js::ErrorReport report(cx);
   CHECK(report.init(cx, exn, js::ErrorReport::WithSideEffects));
--- a/js/src/jsapi-tests/testEmptyWindowIsOmitted.cpp
+++ b/js/src/jsapi-tests/testEmptyWindowIsOmitted.cpp
@@ -80,39 +80,39 @@ bool testUtf16() {
 static bool startsWith(const char* str, const char* prefix) {
   return std::strncmp(prefix, str, strlen(prefix)) == 0;
 }
 
 static bool equals(const char* str, const char* expected) {
   return std::strcmp(str, expected) == 0;
 }
 
-bool compile(const char16_t* chars, size_t len,
-             JS::MutableHandle<JSScript*> script) {
+JSScript* compile(const char16_t* chars, size_t len) {
   JS::SourceText<char16_t> source;
-  CHECK(source.init(cx, chars, len, JS::SourceOwnership::Borrowed));
+  MOZ_RELEASE_ASSERT(
+      source.init(cx, chars, len, JS::SourceOwnership::Borrowed));
 
   JS::CompileOptions options(cx);
-  return JS::Compile(cx, options, source, script);
+  return JS::Compile(cx, options, source);
 }
 
-bool compile(const char* chars, size_t len,
-             JS::MutableHandle<JSScript*> script) {
+JSScript* compile(const char* chars, size_t len) {
   JS::SourceText<Utf8Unit> source;
-  CHECK(source.init(cx, chars, len, JS::SourceOwnership::Borrowed));
+  MOZ_RELEASE_ASSERT(
+      source.init(cx, chars, len, JS::SourceOwnership::Borrowed));
 
   JS::CompileOptions options(cx);
-  return JS::CompileDontInflate(cx, options, source, script);
+  return JS::CompileDontInflate(cx, options, source);
 }
 
 template <typename CharT, size_t N>
 bool testOmittedWindow(const CharT (&chars)[N], unsigned expectedErrorNumber,
                        const char* badCodeUnits = nullptr) {
-  JS::Rooted<JSScript*> script(cx);
-  CHECK(!compile(chars, N - 1, &script));
+  JS::Rooted<JSScript*> script(cx, compile(chars, N - 1));
+  CHECK(!script);
 
   JS::RootedValue exn(cx);
   CHECK(JS_GetPendingException(cx, &exn));
   JS_ClearPendingException(cx);
 
   js::ErrorReport report(cx);
   CHECK(report.init(cx, exn, js::ErrorReport::WithSideEffects));
 
--- a/js/src/jsapi-tests/testExecuteInJSMEnvironment.cpp
+++ b/js/src/jsapi-tests/testExecuteInJSMEnvironment.cpp
@@ -20,19 +20,19 @@ BEGIN_TEST(testExecuteInJSMEnvironment_B
       "(0,eval)('this.f = 6');\n"
       "(function() { this.g = 7; })();\n"
       "function f_h() { this.h = 8; }; f_h();\n";
 
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, __LINE__);
   options.setNoScriptRval(true);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8ForNonSyntacticScope(cx, options, src, sizeof(src) - 1,
-                                            &script));
+  JS::RootedScript script(cx, JS::CompileUtf8ForNonSyntacticScope(
+                                  cx, options, src, sizeof(src) - 1));
+  CHECK(script);
 
   JS::RootedObject varEnv(cx, js::NewJSMEnvironment(cx));
   JS::RootedObject lexEnv(cx, JS_ExtensibleLexicalEnvironment(varEnv));
   CHECK(varEnv && varEnv->is<js::NonSyntacticVariablesObject>());
   CHECK(lexEnv && js::IsExtensibleLexicalEnvironment(lexEnv));
   CHECK(lexEnv->enclosingEnvironment() == varEnv);
 
   JS::RootedValue vi(cx, JS::Int32Value(1000));
@@ -74,19 +74,19 @@ BEGIN_TEST(testExecuteInJSMEnvironment_C
   static const char src[] = "var output = callback();\n";
 
   CHECK(JS_DefineFunctions(cx, global, testFunctions));
 
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, __LINE__);
   options.setNoScriptRval(true);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8ForNonSyntacticScope(cx, options, src, sizeof(src) - 1,
-                                            &script));
+  JS::RootedScript script(cx, JS::CompileUtf8ForNonSyntacticScope(
+                                  cx, options, src, sizeof(src) - 1));
+  CHECK(script);
 
   JS::RootedObject nsvo(cx, js::NewJSMEnvironment(cx));
   CHECK(nsvo);
   CHECK(js::ExecuteInJSMEnvironment(cx, script, nsvo));
 
   JS::RootedValue v(cx);
   CHECK(JS_GetProperty(cx, nsvo, "output", &v) && v == JS::ObjectValue(*nsvo));
 
--- a/js/src/jsapi-tests/testGCCellPtr.cpp
+++ b/js/src/jsapi-tests/testGCCellPtr.cpp
@@ -20,18 +20,17 @@ BEGIN_TEST(testGCCellPtr) {
 
   JS::RootedString str(cx, JS_NewStringCopyZ(cx, "probably foobar"));
   CHECK(str);
 
   const char* code = "function foo() { return 'bar'; }";
 
   JS::CompileOptions opts(cx);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8(cx, opts, code, strlen(code), &script));
+  JS::RootedScript script(cx, JS::CompileUtf8(cx, opts, code, strlen(code)));
   CHECK(script);
 
   CHECK(!JS::GCCellPtr(nullptr));
 
   CHECK(JS::GCCellPtr(obj.get()));
   CHECK(JS::GCCellPtr(obj.get()).kind() == JS::TraceKind::Object);
   CHECK(JS::GCCellPtr(JS::ObjectValue(*obj)).kind() == JS::TraceKind::Object);
 
--- a/js/src/jsapi-tests/testPrivateGCThingValue.cpp
+++ b/js/src/jsapi-tests/testPrivateGCThingValue.cpp
@@ -37,18 +37,19 @@ BEGIN_TEST(testPrivateGCThingValue) {
   CHECK(obj);
 
   // Make a JSScript to stick into a PrivateGCThingValue.
   const char code[] = "'objet petit a'";
 
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, __LINE__);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8(cx, options, code, sizeof(code) - 1, &script));
+  JS::RootedScript script(cx,
+                          JS::CompileUtf8(cx, options, code, sizeof(code) - 1));
+  CHECK(script);
   JS_SetReservedSlot(obj, 0, PrivateGCThingValue(script));
 
   TestTracer trc(cx);
   trc.expectedCell = script;
   trc.expectedKind = JS::TraceKind::Script;
   JS::TraceChildren(&trc, JS::GCCellPtr(obj, JS::TraceKind::Object));
   CHECK(trc.found);
 
--- a/js/src/jsapi-tests/testScriptInfo.cpp
+++ b/js/src/jsapi-tests/testScriptInfo.cpp
@@ -25,18 +25,17 @@ catch (e)          \n\
 //@ sourceMappingURL=http://example.com/path/to/source-map.json";
 
 BEGIN_TEST(testScriptInfo) {
   unsigned startLine = 1000;
 
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, startLine);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8(cx, options, code, strlen(code), &script));
+  JS::RootedScript script(cx, JS::CompileUtf8(cx, options, code, strlen(code)));
   CHECK(script);
 
   CHECK_EQUAL(JS_GetScriptBaseLineNumber(cx, script), startLine);
   CHECK(strcmp(JS_GetScriptFilename(script), __FILE__) == 0);
 
   return true;
 }
 static bool CharsMatch(const char16_t* p, const char* q) {
--- a/js/src/jsapi-tests/testScriptObject.cpp
+++ b/js/src/jsapi-tests/testScriptObject.cpp
@@ -38,180 +38,184 @@ const char ScriptObjectFixture::code[] =
 const int ScriptObjectFixture::code_size =
     sizeof(ScriptObjectFixture::code) - 1;
 char16_t ScriptObjectFixture::uc_code[ScriptObjectFixture::code_size];
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript) {
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, __LINE__);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8(cx, options, code, code_size, &script));
+  JS::RootedScript script(cx, JS::CompileUtf8(cx, options, code, code_size));
+  CHECK(script);
 
   return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript_empty) {
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, __LINE__);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8(cx, options, "", 0, &script));
+  JS::RootedScript script(cx, JS::CompileUtf8(cx, options, "", 0));
+  CHECK(script);
 
   return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScriptForPrincipals) {
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, __LINE__);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8(cx, options, code, code_size, &script));
+  JS::RootedScript script(cx, JS::CompileUtf8(cx, options, code, code_size));
 
   return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScriptForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript) {
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, __LINE__);
 
   JS::SourceText<char16_t> srcBuf;
   CHECK(srcBuf.init(cx, uc_code, code_size, JS::SourceOwnership::Borrowed));
 
-  JS::RootedScript script(cx);
-  CHECK(JS::Compile(cx, options, srcBuf, &script));
+  JS::RootedScript script(cx, JS::Compile(cx, options, srcBuf));
+  CHECK(script);
 
   return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript_empty) {
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, __LINE__);
 
   JS::SourceText<char16_t> srcBuf;
   CHECK(srcBuf.init(cx, uc_code, 0, JS::SourceOwnership::Borrowed));
 
-  JS::RootedScript script(cx);
-  CHECK(JS::Compile(cx, options, srcBuf, &script));
+  JS::RootedScript script(cx, JS::Compile(cx, options, srcBuf));
+  CHECK(script);
 
   return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture,
                    bug438633_JS_CompileUCScriptForPrincipals) {
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, __LINE__);
 
   JS::SourceText<char16_t> srcBuf;
   CHECK(srcBuf.init(cx, uc_code, code_size, JS::SourceOwnership::Borrowed));
 
-  JS::RootedScript script(cx);
-  CHECK(JS::Compile(cx, options, srcBuf, &script));
+  JS::RootedScript script(cx, JS::Compile(cx, options, srcBuf));
+  CHECK(script);
 
   return tryScript(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);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8Path(cx, options, script_filename, &script));
+  JS::RootedScript script(cx,
+                          JS::CompileUtf8Path(cx, options, script_filename));
+  CHECK(script);
 
   tempScript.remove();
   return tryScript(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);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8Path(cx, options, script_filename, &script));
+  JS::RootedScript script(cx,
+                          JS::CompileUtf8Path(cx, options, script_filename));
+  CHECK(script);
 
   tempScript.remove();
   return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle) {
   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("temporary file", 1);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8File(cx, options, script_stream, &script));
+  JS::RootedScript script(cx, JS::CompileUtf8File(cx, options, script_stream));
+  CHECK(script);
+
   return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle_empty) {
   TempFile tempScript;
   FILE* script_stream =
       tempScript.open("temp-bug438633_JS_CompileFileHandle_empty");
 
   JS::CompileOptions options(cx);
   options.setFileAndLine("empty temporary file", 1);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8File(cx, options, script_stream, &script));
+  JS::RootedScript script(cx, JS::CompileUtf8File(cx, options, script_stream));
+  CHECK(script);
+
   return tryScript(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);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8File(cx, options, script_stream, &script));
+  JS::RootedScript script(cx, JS::CompileUtf8File(cx, options, script_stream));
+  CHECK(script);
+
   return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture,
                  bug438633_JS_CompileFileHandleForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, CloneAndExecuteScript) {
   JS::RootedValue fortyTwo(cx);
   fortyTwo.setInt32(42);
   CHECK(JS_SetProperty(cx, global, "val", fortyTwo));
 
   JS::CompileOptions options(cx);
   options.setFileAndLine(__FILE__, __LINE__);
 
-  JS::RootedScript script(cx);
-  CHECK(JS::CompileUtf8(cx, options, "val", 3, &script));
+  JS::RootedScript script(cx, JS::CompileUtf8(cx, options, "val", 3));
+  CHECK(script);
 
   JS::RootedValue value(cx);
   CHECK(JS_ExecuteScript(cx, script, &value));
   CHECK(value.toInt32() == 42);
   {
     JS::RootedObject global2(cx, createGlobal());
     CHECK(global2);
     JSAutoRealm ar(cx, global2);
--- a/js/src/jsapi-tests/testUbiNode.cpp
+++ b/js/src/jsapi-tests/testUbiNode.cpp
@@ -86,29 +86,29 @@ BEGIN_TEST(test_ubiNodeZone) {
   CHECK(JS::ubi::Node(global2).zone() != global1->zone());
 
   JS::CompileOptions options(cx);
 
   // Create a string and a script in the original zone...
   RootedString string1(
       cx, JS_NewStringCopyZ(cx, "Simpson's Individual Stringettes!"));
   CHECK(string1);
-  RootedScript script1(cx);
-  CHECK(JS::CompileUtf8(cx, options, "", 0, &script1));
+  RootedScript script1(cx, JS::CompileUtf8(cx, options, "", 0));
+  CHECK(script1);
 
   {
     // ... and then enter global2's zone and create a string and script
     // there, too.
     JSAutoRealm ar(cx, global2);
 
     RootedString string2(cx,
                          JS_NewStringCopyZ(cx, "A million household uses!"));
     CHECK(string2);
-    RootedScript script2(cx);
-    CHECK(JS::CompileUtf8(cx, options, "", 0, &script2));
+    RootedScript script2(cx, JS::CompileUtf8(cx, options, "", 0));
+    CHECK(script2);
 
     CHECK(JS::ubi::Node(string1).zone() == global1->zone());
     CHECK(JS::ubi::Node(script1).zone() == global1->zone());
 
     CHECK(JS::ubi::Node(string2).zone() == global2->zone());
     CHECK(JS::ubi::Node(script2).zone() == global2->zone());
   }
 
@@ -132,26 +132,26 @@ BEGIN_TEST(test_ubiNodeCompartment) {
   CHECK(JS::ubi::Node(global2).compartment() == global2->compartment());
   CHECK(JS::ubi::Node(global2).compartment() != global1->compartment());
   CHECK(JS::ubi::Node(global2).realm() == global2->nonCCWRealm());
   CHECK(JS::ubi::Node(global2).realm() != global1->nonCCWRealm());
 
   JS::CompileOptions options(cx);
 
   // Create a script in the original realm...
-  RootedScript script1(cx);
-  CHECK(JS::CompileUtf8(cx, options, "", 0, &script1));
+  RootedScript script1(cx, JS::CompileUtf8(cx, options, "", 0));
+  CHECK(script1);
 
   {
     // ... and then enter global2's realm and create a script
     // there, too.
     JSAutoRealm ar(cx, global2);
 
-    RootedScript script2(cx);
-    CHECK(JS::CompileUtf8(cx, options, "", 0, &script2));
+    RootedScript script2(cx, JS::CompileUtf8(cx, options, "", 0));
+    CHECK(script2);
 
     CHECK(JS::ubi::Node(script1).compartment() == global1->compartment());
     CHECK(JS::ubi::Node(script2).compartment() == global2->compartment());
     CHECK(JS::ubi::Node(script1).realm() == global1->nonCCWRealm());
     CHECK(JS::ubi::Node(script2).realm() == global2->nonCCWRealm());
 
     // Now create a wrapper for global1 in global2's compartment.
     RootedObject wrappedGlobal1(cx, global1);
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -56,18 +56,17 @@ BEGIN_TEST(testXDR_bug506491) {
       "    return 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);
-  CHECK(JS::CompileUtf8(cx, options, s, strlen(s), &script));
+  JS::RootedScript script(cx, JS::CompileUtf8(cx, options, s, strlen(s)));
   CHECK(script);
 
   script = FreezeThaw(cx, script);
   CHECK(script);
 
   // execute
   JS::RootedValue v2(cx);
   CHECK(JS_ExecuteScript(cx, script, &v2));
@@ -83,18 +82,17 @@ 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);
-  CHECK(JS::CompileUtf8(cx, options, "", 0, &script));
+  JS::RootedScript script(cx, JS::CompileUtf8(cx, options, "", 0));
   CHECK(script);
 
   script = FreezeThaw(cx, script);
   CHECK(script);
 
   // execute with null result meaning no result wanted
   CHECK(JS_ExecuteScript(cx, script));
   return true;
@@ -113,18 +111,17 @@ BEGIN_TEST(testXDR_source) {
       "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);
-    CHECK(JS::CompileUtf8(cx, options, *s, strlen(*s), &script));
+    JS::RootedScript script(cx, JS::CompileUtf8(cx, options, *s, strlen(*s)));
     CHECK(script);
 
     script = FreezeThaw(cx, script);
     CHECK(script);
 
     JSString* out = JS_DecompileScript(cx, script);
     CHECK(out);
 
@@ -139,17 +136,17 @@ END_TEST(testXDR_source)
 BEGIN_TEST(testXDR_sourceMap) {
   const char* sourceMaps[] = {"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__);
 
-    CHECK(JS::CompileUtf8(cx, options, "", 0, &script));
+    script = JS::CompileUtf8(cx, options, "", 0);
     CHECK(script);
 
     size_t len = strlen(*sm);
     JS::UniqueTwoByteChars expected_wrapper(js::InflateString(cx, *sm, len));
     char16_t* expected = expected_wrapper.get();
     CHECK(expected);
 
     // The script source takes responsibility of free'ing |expected|.
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -856,26 +856,24 @@ static MOZ_MUST_USE bool RunFile(JSConte
         .setFileAndLine(filename, 1)
         .setIsRunOnce(true)
         .setNoScriptRval(true);
 
     if (compileMethod == CompileUtf8::DontInflate) {
       fprintf(stderr, "(compiling '%s' as UTF-8 without inflating)\n",
               filename);
 
-      if (!JS::CompileUtf8FileDontInflate(cx, options, file, &script)) {
-        return false;
-      }
+      script = JS::CompileUtf8FileDontInflate(cx, options, file);
     } else {
-      if (!JS::CompileUtf8File(cx, options, file, &script)) {
-        return false;
-      }
-    }
-
-    MOZ_ASSERT(script);
+      script = JS::CompileUtf8File(cx, options, file);
+    }
+
+    if (!script) {
+      return false;
+    }
   }
 
   if (!RegisterScriptPathWithModuleLoader(cx, script, filename)) {
     return false;
   }
 
 #ifdef DEBUG
   if (dumpEntrainedVariables) {
@@ -1263,18 +1261,18 @@ static MOZ_MUST_USE bool EvalUtf8AndPrin
                                           size_t length, int lineno,
                                           bool compileOnly) {
   // Eval.
   JS::CompileOptions options(cx);
   options.setIntroductionType("js shell interactive")
       .setIsRunOnce(true)
       .setFileAndLine("typein", lineno);
 
-  RootedScript script(cx);
-  if (!JS::CompileUtf8(cx, options, bytes, length, &script)) {
+  RootedScript script(cx, JS::CompileUtf8(cx, options, bytes, length));
+  if (!script) {
     return false;
   }
   if (compileOnly) {
     return true;
   }
   RootedValue result(cx);
   if (!JS_ExecuteScript(cx, script, &result)) {
     return false;
@@ -1721,20 +1719,19 @@ static bool LoadScript(JSContext* cx, un
 
     errno = 0;
 
     CompileOptions opts(cx);
     opts.setIntroductionType("js shell load")
         .setIsRunOnce(true)
         .setNoScriptRval(true);
 
-    RootedScript script(cx);
     RootedValue unused(cx);
     if (!(compileOnly
-              ? JS::CompileUtf8Path(cx, opts, filename.get(), &script)
+              ? JS::CompileUtf8Path(cx, opts, filename.get()) != nullptr
               : JS::EvaluateUtf8Path(cx, opts, filename.get(), &unused))) {
       return false;
     }
   }
 
   args.rval().setUndefined();
   return true;
 }
@@ -2189,19 +2186,19 @@ static bool Evaluate(JSContext* cx, unsi
         mozilla::Range<const char16_t> chars = codeChars.twoByteRange();
         JS::SourceText<char16_t> srcBuf;
         if (!srcBuf.init(cx, chars.begin().get(), chars.length(),
                          JS::SourceOwnership::Borrowed)) {
           return false;
         }
 
         if (envChain.length() == 0) {
-          (void)JS::Compile(cx, options, srcBuf, &script);
+          script = JS::Compile(cx, options, srcBuf);
         } else {
-          (void)JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script);
+          script = JS::CompileForNonSyntacticScope(cx, options, srcBuf);
         }
       }
 
       if (!script) {
         return false;
       }
     }
 
@@ -2448,17 +2445,18 @@ static bool Run(JSContext* cx, unsigned 
     }
 
     JS::CompileOptions options(cx);
     options.setIntroductionType("js shell run")
         .setFileAndLine(filename.get(), 1)
         .setIsRunOnce(true)
         .setNoScriptRval(true);
 
-    if (!JS::Compile(cx, options, srcBuf, &script)) {
+    script = JS::Compile(cx, options, srcBuf);
+    if (!script) {
       return false;
     }
   }
 
   if (!JS_ExecuteScript(cx, script)) {
     return false;
   }
 
@@ -3450,17 +3448,18 @@ static bool DisassFile(JSContext* cx, un
 
   {
     CompileOptions options(cx);
     options.setIntroductionType("js shell disFile")
         .setFileAndLine(filename.get(), 1)
         .setIsRunOnce(true)
         .setNoScriptRval(true);
 
-    if (!JS::CompileUtf8Path(cx, options, filename.get(), &script)) {
+    script = JS::CompileUtf8Path(cx, options, filename.get());
+    if (!script) {
       return false;
     }
   }
 
   Sprinter sprinter(cx);
   if (!sprinter.init()) {
     return false;
   }
@@ -4020,21 +4019,24 @@ static void WorkerMain(WorkerInput* inpu
     }
 
     JSAutoRealm ar(cx, global);
 
     JS::CompileOptions options(cx);
     options.setFileAndLine("<string>", 1).setIsRunOnce(true);
 
     AutoReportException are(cx);
-    RootedScript script(cx);
     JS::SourceText<char16_t> srcBuf;
     if (!srcBuf.init(cx, input->chars.get(), input->length,
-                     JS::SourceOwnership::Borrowed) ||
-        !JS::Compile(cx, options, srcBuf, &script)) {
+                     JS::SourceOwnership::Borrowed)) {
+      break;
+    }
+
+    RootedScript script(cx, JS::Compile(cx, options, srcBuf));
+    if (!script) {
       break;
     }
     RootedValue result(cx);
     JS_ExecuteScript(cx, script, &result);
   } while (0);
 
   KillWatchdog(cx);
   JS_SetGrayGCRootsTracer(cx, nullptr, nullptr);
@@ -4659,18 +4661,18 @@ static bool Compile(JSContext* cx, unsig
       .setNoScriptRval(true);
 
   JS::SourceText<char16_t> srcBuf;
   if (!srcBuf.init(cx, stableChars.twoByteRange().begin().get(),
                    scriptContents->length(), JS::SourceOwnership::Borrowed)) {
     return false;
   }
 
-  RootedScript script(cx);
-  if (!JS::Compile(cx, options, srcBuf, &script)) {
+  RootedScript script(cx, JS::Compile(cx, options, srcBuf));
+  if (!script) {
     return false;
   }
 
   args.rval().setUndefined();
   return true;
 }
 
 static ShellCompartmentPrivate* EnsureShellCompartmentPrivate(JSContext* cx) {
--- a/js/src/vm/CompilationAndEvaluation.cpp
+++ b/js/src/vm/CompilationAndEvaluation.cpp
@@ -50,141 +50,134 @@ using JS::UTF8CharsToNewTwoByteCharsZ;
 using namespace js;
 
 JS_PUBLIC_API void JS::detail::ReportSourceTooLong(JSContext* cx) {
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                             JSMSG_SOURCE_TOO_LONG);
 }
 
 template <typename Unit>
-static bool CompileSourceBuffer(JSContext* cx,
-                                const ReadOnlyCompileOptions& options,
-                                SourceText<Unit>& srcBuf,
-                                JS::MutableHandleScript script) {
+static JSScript* CompileSourceBuffer(JSContext* cx,
+                                     const ReadOnlyCompileOptions& options,
+                                     SourceText<Unit>& srcBuf) {
   ScopeKind scopeKind =
       options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global;
 
   MOZ_ASSERT(!cx->zone()->isAtomsZone());
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
 
   frontend::GlobalScriptInfo info(cx, options, scopeKind);
-  script.set(frontend::CompileGlobalScript(info, srcBuf));
-  return !!script;
+  return frontend::CompileGlobalScript(info, srcBuf);
 }
 
-static bool CompileUtf8(JSContext* cx, const ReadOnlyCompileOptions& options,
-                        const char* bytes, size_t length,
-                        JS::MutableHandleScript script) {
+static JSScript* CompileUtf8(JSContext* cx,
+                             const ReadOnlyCompileOptions& options,
+                             const char* bytes, size_t length) {
   auto chars = UniqueTwoByteChars(
       UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
   if (!chars) {
-    return false;
+    return nullptr;
   }
 
   SourceText<char16_t> source;
   if (!source.init(cx, std::move(chars), length)) {
-    return false;
+    return nullptr;
   }
 
-  return CompileSourceBuffer(cx, options, source, script);
+  return CompileSourceBuffer(cx, options, source);
 }
 
-static bool CompileUtf8DontInflate(JSContext* cx,
-                                   const ReadOnlyCompileOptions& options,
-                                   const char* bytes, size_t length,
-                                   JS::MutableHandleScript script) {
+static JSScript* CompileUtf8DontInflate(JSContext* cx,
+                                        const ReadOnlyCompileOptions& options,
+                                        const char* bytes, size_t length) {
   SourceText<Utf8Unit> source;
   if (!source.init(cx, bytes, length, SourceOwnership::Borrowed)) {
-    return false;
+    return nullptr;
   }
 
-  return CompileSourceBuffer(cx, options, source, script);
+  return CompileSourceBuffer(cx, options, source);
 }
 
-bool JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
-                 SourceText<char16_t>& srcBuf, JS::MutableHandleScript script) {
-  return CompileSourceBuffer(cx, options, srcBuf, script);
+JSScript* JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
+                      SourceText<char16_t>& srcBuf) {
+  return CompileSourceBuffer(cx, options, srcBuf);
 }
 
-bool JS::CompileDontInflate(JSContext* cx,
-                            const ReadOnlyCompileOptions& options,
-                            SourceText<Utf8Unit>& srcBuf,
-                            JS::MutableHandleScript script) {
-  return CompileSourceBuffer(cx, options, srcBuf, script);
+JSScript* JS::CompileDontInflate(JSContext* cx,
+                                 const ReadOnlyCompileOptions& options,
+                                 SourceText<Utf8Unit>& srcBuf) {
+  return CompileSourceBuffer(cx, options, srcBuf);
 }
 
-bool JS::CompileUtf8(JSContext* cx, const ReadOnlyCompileOptions& options,
-                     const char* bytes, size_t length,
-                     JS::MutableHandleScript script) {
-  return ::CompileUtf8(cx, options, bytes, length, script);
+JSScript* JS::CompileUtf8(JSContext* cx, const ReadOnlyCompileOptions& options,
+                          const char* bytes, size_t length) {
+  return ::CompileUtf8(cx, options, bytes, length);
 }
 
-bool JS::CompileUtf8DontInflate(JSContext* cx,
-                                const ReadOnlyCompileOptions& options,
-                                const char* bytes, size_t length,
-                                JS::MutableHandleScript script) {
-  return ::CompileUtf8DontInflate(cx, options, bytes, length, script);
+JSScript* JS::CompileUtf8DontInflate(JSContext* cx,
+                                     const ReadOnlyCompileOptions& options,
+                                     const char* bytes, size_t length) {
+  return ::CompileUtf8DontInflate(cx, options, bytes, length);
 }
 
-bool JS::CompileUtf8File(JSContext* cx, const ReadOnlyCompileOptions& options,
-                         FILE* file, JS::MutableHandleScript script) {
+JSScript* JS::CompileUtf8File(JSContext* cx,
+                              const ReadOnlyCompileOptions& options,
+                              FILE* file) {
   FileContents buffer(cx);
   if (!ReadCompleteFile(cx, file, buffer)) {
-    return false;
+    return nullptr;
   }
 
   return ::CompileUtf8(cx, options,
                        reinterpret_cast<const char*>(buffer.begin()),
-                       buffer.length(), script);
+                       buffer.length());
 }
 
-bool JS::CompileUtf8FileDontInflate(JSContext* cx,
-                                    const ReadOnlyCompileOptions& options,
-                                    FILE* file,
-                                    JS::MutableHandleScript script) {
+JSScript* JS::CompileUtf8FileDontInflate(JSContext* cx,
+                                         const ReadOnlyCompileOptions& options,
+                                         FILE* file) {
   FileContents buffer(cx);
   if (!ReadCompleteFile(cx, file, buffer)) {
-    return false;
+    return nullptr;
   }
 
   return ::CompileUtf8DontInflate(cx, options,
                                   reinterpret_cast<const char*>(buffer.begin()),
-                                  buffer.length(), script);
+                                  buffer.length());
 }
 
-bool JS::CompileUtf8Path(JSContext* cx,
-                         const ReadOnlyCompileOptions& optionsArg,
-                         const char* filename, JS::MutableHandleScript script) {
+JSScript* JS::CompileUtf8Path(JSContext* cx,
+                              const ReadOnlyCompileOptions& optionsArg,
+                              const char* filename) {
   AutoFile file;
   if (!file.open(cx, filename)) {
-    return false;
+    return nullptr;
   }
 
   CompileOptions options(cx, optionsArg);
   options.setFileAndLine(filename, 1);
-  return CompileUtf8File(cx, options, file.fp(), script);
+  return CompileUtf8File(cx, options, file.fp());
 }
 
-bool JS::CompileForNonSyntacticScope(JSContext* cx,
-                                     const ReadOnlyCompileOptions& optionsArg,
-                                     SourceText<char16_t>& srcBuf,
-                                     JS::MutableHandleScript script) {
+JSScript* JS::CompileForNonSyntacticScope(
+    JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
+    SourceText<char16_t>& srcBuf) {
   CompileOptions options(cx, optionsArg);
   options.setNonSyntacticScope(true);
-  return CompileSourceBuffer(cx, options, srcBuf, script);
+  return CompileSourceBuffer(cx, options, srcBuf);
 }
 
-bool JS::CompileUtf8ForNonSyntacticScope(
+JSScript* JS::CompileUtf8ForNonSyntacticScope(
     JSContext* cx, const ReadOnlyCompileOptions& optionsArg, const char* bytes,
-    size_t length, JS::MutableHandleScript script) {
+    size_t length) {
   CompileOptions options(cx, optionsArg);
   options.setNonSyntacticScope(true);
 
-  return ::CompileUtf8(cx, options, bytes, length, script);
+  return ::CompileUtf8(cx, options, bytes, length);
 }
 
 JS_PUBLIC_API bool JS_Utf8BufferIsCompilableUnit(JSContext* cx,
                                                  HandleObject obj,
                                                  const char* utf8,
                                                  size_t length) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
--- a/js/xpconnect/loader/ChromeScriptLoader.cpp
+++ b/js/xpconnect/loader/ChromeScriptLoader.cpp
@@ -139,18 +139,18 @@ bool AsyncScriptCompiler::StartCompile(J
                               static_cast<void*>(this))) {
       return false;
     }
 
     NS_ADDREF(this);
     return true;
   }
 
-  Rooted<JSScript*> script(aCx);
-  if (!JS::Compile(aCx, mOptions, srcBuf, &script)) {
+  Rooted<JSScript*> script(aCx, JS::Compile(aCx, mOptions, srcBuf));
+  if (!script) {
     return false;
   }
 
   Finish(aCx, script);
   return true;
 }
 
 NS_IMETHODIMP
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -851,32 +851,26 @@ nsresult mozJSComponentLoader::ObjectFor
 
     if (realFile) {
       AutoMemMap map;
       MOZ_TRY(map.init(aComponentFile));
 
       // Note: exceptions will get handled further down;
       // don't early return for them here.
       auto buf = map.get<char>();
-      if (reuseGlobal) {
-        CompileUtf8ForNonSyntacticScope(cx, options, buf.get(), map.size(),
-                                        &script);
-      } else {
-        CompileUtf8(cx, options, buf.get(), map.size(), &script);
-      }
+      script = reuseGlobal ? CompileUtf8ForNonSyntacticScope(
+                                 cx, options, buf.get(), map.size())
+                           : CompileUtf8(cx, options, buf.get(), map.size());
     } else {
       nsCString str;
       MOZ_TRY_VAR(str, ReadScript(aInfo));
 
-      if (reuseGlobal) {
-        CompileUtf8ForNonSyntacticScope(cx, options, str.get(), str.Length(),
-                                        &script);
-      } else {
-        CompileUtf8(cx, options, str.get(), str.Length(), &script);
-      }
+      script = reuseGlobal ? CompileUtf8ForNonSyntacticScope(
+                                 cx, options, str.get(), str.Length())
+                           : CompileUtf8(cx, options, str.get(), str.Length());
     }
     // Propagate the exception, if one exists. Also, don't leave the stale
     // exception on this context.
     if (!script && aPropagateExceptions && jsapi.HasException()) {
       if (!jsapi.StealException(aException)) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
     }
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -121,36 +121,37 @@ static void ReportError(JSContext* cx, c
   }
 
   nsAutoCString msg(origMsg);
   msg.AppendLiteral(": ");
   msg.Append(spec);
   ReportError(cx, msg);
 }
 
-static bool PrepareScript(nsIURI* uri, JSContext* cx, bool wantGlobalScript,
-                          const char* uriStr, const char* buf, int64_t len,
-                          bool wantReturnValue, MutableHandleScript script) {
+static JSScript* PrepareScript(nsIURI* uri, JSContext* cx,
+                               bool wantGlobalScript, const char* uriStr,
+                               const char* buf, int64_t len,
+                               bool wantReturnValue) {
   JS::CompileOptions options(cx);
   options.setFileAndLine(uriStr, 1).setNoScriptRval(!wantReturnValue);
 
   // This presumes that no one else might be compiling a script for this
   // (URL, syntactic-or-not) key *not* using UTF-8.  Seeing as JS source can
   // only be compiled as UTF-8 or UTF-16 now -- there isn't a JSAPI function to
   // compile Latin-1 now -- this presumption seems relatively safe.
   //
   // This also presumes that lazy parsing is disabled, for the sake of the
   // startup cache.  If lazy parsing is ever enabled for pertinent scripts that
   // pass through here, we may need to disable lazy source for them.
   options.setSourceIsLazy(true);
 
   if (wantGlobalScript) {
-    return JS::CompileUtf8(cx, options, buf, len, script);
+    return JS::CompileUtf8(cx, options, buf, len);
   }
-  return JS::CompileUtf8ForNonSyntacticScope(cx, options, buf, len, script);
+  return JS::CompileUtf8ForNonSyntacticScope(cx, options, buf, len);
 }
 
 static bool EvalScript(JSContext* cx, HandleObject targetObj,
                        HandleObject loadScope, MutableHandleValue retval,
                        nsIURI* uri, bool startupCache, bool preloadCache,
                        MutableHandleScript script) {
   MOZ_ASSERT(!js::IsWrapper(targetObj));
 
@@ -367,19 +368,20 @@ AsyncScriptLoader::OnStreamComplete(nsII
   RootedScript script(cx);
   nsAutoCString spec;
   nsresult rv = uri->GetSpec(spec);
   NS_ENSURE_SUCCESS(rv, rv);
 
   RootedObject targetObj(cx, mTargetObj);
   RootedObject loadScope(cx, mLoadScope);
 
-  if (!PrepareScript(uri, cx, JS_IsGlobalObject(targetObj), spec.get(),
-                     reinterpret_cast<const char*>(aBuf), aLength,
-                     mWantReturnValue, &script)) {
+  script = PrepareScript(uri, cx, JS_IsGlobalObject(targetObj), spec.get(),
+                         reinterpret_cast<const char*>(aBuf), aLength,
+                         mWantReturnValue);
+  if (!script) {
     return NS_OK;
   }
 
   JS::Rooted<JS::Value> retval(cx);
   if (EvalScript(cx, targetObj, loadScope, &retval, uri, mCache,
                  mCache && !mWantReturnValue, &script)) {
     autoPromise.ResolvePromise(retval);
   }
@@ -435,24 +437,19 @@ nsresult mozJSSubScriptLoader::ReadScrip
   nsCOMPtr<nsIIncrementalStreamLoader> loader;
   rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), loadObserver);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIStreamListener> listener = loader.get();
   return channel->AsyncOpen(listener);
 }
 
-bool mozJSSubScriptLoader::ReadScript(nsIURI* uri, JSContext* cx,
-                                      HandleObject targetObj,
-                                      const char* uriStr, nsIIOService* serv,
-                                      bool wantReturnValue,
-                                      bool useCompilationScope,
-                                      MutableHandleScript script) {
-  script.set(nullptr);
-
+JSScript* mozJSSubScriptLoader::ReadScript(
+    nsIURI* uri, JSContext* cx, HandleObject targetObj, const char* uriStr,
+    nsIIOService* serv, bool wantReturnValue, bool useCompilationScope) {
   // We create a channel and call SetContentType, to avoid expensive MIME type
   // lookups (bug 632490).
   nsCOMPtr<nsIChannel> chan;
   nsCOMPtr<nsIInputStream> instream;
   nsresult rv;
   rv = NS_NewChannel(getter_AddRefs(chan), uri,
                      nsContentUtils::GetSystemPrincipal(),
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
@@ -465,52 +462,52 @@ bool mozJSSubScriptLoader::ReadScript(ns
 
   if (NS_SUCCEEDED(rv)) {
     chan->SetContentType(NS_LITERAL_CSTRING("application/javascript"));
     rv = chan->Open(getter_AddRefs(instream));
   }
 
   if (NS_FAILED(rv)) {
     ReportError(cx, LOAD_ERROR_NOSTREAM, uri);
-    return false;
+    return nullptr;
   }
 
   int64_t len = -1;
 
   rv = chan->GetContentLength(&len);
   if (NS_FAILED(rv) || len == -1) {
     ReportError(cx, LOAD_ERROR_NOCONTENT, uri);
-    return false;
+    return nullptr;
   }
 
   if (len > INT32_MAX) {
     ReportError(cx, LOAD_ERROR_CONTENTTOOBIG, uri);
-    return false;
+    return nullptr;
   }
 
   nsCString buf;
   rv = NS_ReadInputStreamToString(instream, buf, len);
-  NS_ENSURE_SUCCESS(rv, false);
+  NS_ENSURE_SUCCESS(rv, nullptr);
 
   Maybe<JSAutoRealm> ar;
 
   // Note that when using the ScriptPreloader cache with loadSubScript, there
   // will be a side-effect of keeping the global that the script was compiled
   // for alive. See note above in EvalScript().
   //
   // This will compile the script in XPConnect compilation scope. When the
   // script is evaluated, it will be cloned into the target scope to be
   // executed, avoiding leaks on the first session when we don't have a
   // startup cache.
   if (useCompilationScope) {
     ar.emplace(cx, xpc::CompilationScope());
   }
 
   return PrepareScript(uri, cx, JS_IsGlobalObject(targetObj), uriStr, buf.get(),
-                       len, wantReturnValue, script);
+                       len, wantReturnValue);
 }
 
 NS_IMETHODIMP
 mozJSSubScriptLoader::LoadSubScript(const nsAString& url, HandleValue target,
                                     JSContext* cx, MutableHandleValue retval) {
   /*
    * Loads a local url, referring to UTF-8-encoded data, and evals it into the
    * current cx.  Synchronous (an async version would be cool too.)
@@ -667,18 +664,21 @@ nsresult mozJSSubScriptLoader::DoLoadSub
     return ReadScriptAsync(uri, targetObj, loadScope, serv,
                            options.wantReturnValue, !!cache, retval);
   }
 
   if (script) {
     // |script| came from the cache, so don't bother writing it
     // |back there.
     cache = nullptr;
-  } else if (!ReadScript(
-                 uri, cx, targetObj, static_cast<const char*>(uriStr.get()),
-                 serv, options.wantReturnValue, useCompilationScope, &script)) {
-    return NS_OK;
+  } else {
+    script =
+        ReadScript(uri, cx, targetObj, static_cast<const char*>(uriStr.get()),
+                   serv, options.wantReturnValue, useCompilationScope);
+    if (!script) {
+      return NS_OK;
+    }
   }
 
   Unused << EvalScript(cx, targetObj, loadScope, retval, uri, !!cache,
                        !ignoreCache && !options.wantReturnValue, &script);
   return NS_OK;
 }
--- a/js/xpconnect/loader/mozJSSubScriptLoader.h
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.h
@@ -26,19 +26,19 @@ class mozJSSubScriptLoader : public mozI
 
   // all the interface method declarations...
   NS_DECL_ISUPPORTS
   NS_DECL_MOZIJSSUBSCRIPTLOADER
 
  private:
   virtual ~mozJSSubScriptLoader();
 
-  bool ReadScript(nsIURI* uri, JSContext* cx, JS::HandleObject targetObj,
-                  const char* uriStr, nsIIOService* serv, bool wantReturnValue,
-                  bool useCompilationScope, JS::MutableHandleScript script);
+  JSScript* ReadScript(nsIURI* uri, JSContext* cx, JS::HandleObject targetObj,
+                       const char* uriStr, nsIIOService* serv,
+                       bool wantReturnValue, bool useCompilationScope);
 
   nsresult ReadScriptAsync(nsIURI* uri, JS::HandleObject targetObj,
                            JS::HandleObject loadScope, nsIIOService* serv,
                            bool wantReturnValue, bool cache,
                            JS::MutableHandleValue retval);
 
   nsresult DoLoadSubScriptWithOptions(const nsAString& url,
                                       LoadSubScriptOptions& options,
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -362,17 +362,17 @@ static bool Load(JSContext* cx, unsigned
       JS_ReportErrorUTF8(cx, "cannot open file '%s' for reading",
                          filename.get());
       return false;
     }
     JS::CompileOptions options(cx);
     options.setFileAndLine(filename.get(), 1).setIsRunOnce(true);
     JS::Rooted<JSScript*> script(cx);
     JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
-    JS::CompileUtf8File(cx, options, file, &script);
+    script = JS::CompileUtf8File(cx, options, file);
     fclose(file);
     if (!script) {
       return false;
     }
 
     if (!compileOnly) {
       if (!JS_ExecuteScript(cx, script)) {
         return false;
@@ -694,18 +694,19 @@ static const JSErrorFormatString* my_Get
 }
 
 static bool ProcessUtf8Line(AutoJSAPI& jsapi, const char* buffer,
                             int startline) {
   JSContext* cx = jsapi.cx();
   JS::CompileOptions options(cx);
   options.setFileAndLine("typein", startline).setIsRunOnce(true);
 
-  JS::RootedScript script(cx);
-  if (!JS::CompileUtf8(cx, options, buffer, strlen(buffer), &script)) {
+  JS::RootedScript script(cx,
+                          JS::CompileUtf8(cx, options, buffer, strlen(buffer)));
+  if (!script) {
     return false;
   }
   if (compileOnly) {
     return true;
   }
 
   JS::RootedValue result(cx);
   if (!JS_ExecuteScript(cx, script, &result)) {
@@ -758,17 +759,18 @@ static bool ProcessFile(AutoJSAPI& jsapi
     ungetc(ch, file);
 
     JS::RootedScript script(cx);
     JS::RootedValue unused(cx);
     JS::CompileOptions options(cx);
     options.setFileAndLine(filename, 1)
         .setIsRunOnce(true)
         .setNoScriptRval(true);
-    if (!JS::CompileUtf8File(cx, options, file, &script)) {
+    script = JS::CompileUtf8File(cx, options, file);
+    if (!script) {
       return false;
     }
     return compileOnly || JS_ExecuteScript(cx, script, &unused);
   }
 
   /* It's an interactive filehandle; drop into read-eval-print loop. */
   int lineno = 1;
   bool hitEOF = false;
--- a/netwerk/base/ProxyAutoConfig.cpp
+++ b/netwerk/base/ProxyAutoConfig.cpp
@@ -701,44 +701,43 @@ nsresult ProxyAutoConfig::SetupJS() {
   // use nsIURI scheme methods
   bool isDataURI =
       nsDependentCSubstring(mPACURI, 0, 5).LowerCaseEqualsASCII("data:", 5);
 
   SetRunning(this);
 
   JS::Rooted<JSObject *> global(cx, mJSContext->Global());
 
-  auto CompilePACScript = [this](JSContext *cx,
-                                 JS::MutableHandle<JSScript *> script) {
+  auto CompilePACScript = [this](JSContext *cx) -> JSScript * {
     JS::CompileOptions options(cx);
     options.setFileAndLine(this->mPACURI.get(), 1);
 
     // Per ProxyAutoConfig::Init, compile as UTF-8 if the full data is UTF-8,
     // and otherwise inflate Latin-1 to UTF-16 and compile that.
     const char *scriptData = this->mConcatenatedPACData.get();
     size_t scriptLength = this->mConcatenatedPACData.Length();
     if (mozilla::IsValidUtf8(scriptData, scriptLength)) {
-      return JS::CompileUtf8(cx, options, scriptData, scriptLength, script);
+      return JS::CompileUtf8(cx, options, scriptData, scriptLength);
     }
 
     // nsReadableUtils.h says that "ASCII" is a misnomer "for legacy reasons",
     // and this handles not just ASCII but Latin-1 too.
     NS_ConvertASCIItoUTF16 inflated(this->mConcatenatedPACData);
 
     JS::SourceText<char16_t> source;
     if (!source.init(cx, inflated.get(), inflated.Length(),
                      JS::SourceOwnership::Borrowed)) {
-      return false;
+      return nullptr;
     }
 
-    return JS::Compile(cx, options, source, script);
+    return JS::Compile(cx, options, source);
   };
 
-  JS::Rooted<JSScript *> script(cx);
-  if (!CompilePACScript(cx, &script) || !JS_ExecuteScript(cx, script)) {
+  JS::Rooted<JSScript *> script(cx, CompilePACScript(cx));
+  if (!script || !JS_ExecuteScript(cx, 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);