Bug 1475228 - Make synchronous compile APIs take SourceBufferHolders exclusively r=jandem
☠☠ backed out by e8525a46fd9d ☠ ☠
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 17 Jul 2018 14:30:22 +0100
changeset 429157 34fb24d52f08a8ebc04886f2e140ab42b80d3599
parent 429156 7252e88797e3912780c4a2637da8ff8e0e30f90b
child 429158 7c83633262dbf3547bdf3343807648c3e4cc8f98
push id105816
push userjcoppeard@mozilla.com
push dateMon, 30 Jul 2018 10:16:40 +0000
treeherdermozilla-inbound@b2d18ea619ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1475228
milestone63.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 1475228 - Make synchronous compile APIs take SourceBufferHolders exclusively r=jandem
dom/base/nsJSUtils.cpp
dom/workers/WorkerPrivate.cpp
ipc/testshell/XPCShellEnvironment.cpp
js/src/builtin/TestingFunctions.cpp
js/src/jsapi-tests/testCompileNonSyntactic.cpp
js/src/jsapi-tests/testErrorLineOfContext.cpp
js/src/jsapi-tests/testJSEvaluateScript.cpp
js/src/jsapi-tests/testMutedErrors.cpp
js/src/jsapi-tests/testScriptObject.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/shell/js.cpp
js/xpconnect/loader/ChromeScriptLoader.cpp
js/xpconnect/src/Sandbox.cpp
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -89,21 +89,22 @@ nsJSUtils::CompileFunction(AutoJSAPI& js
 
   // Do the junk Gecko is supposed to do before calling into JSAPI.
   for (size_t i = 0; i < aScopeChain.length(); ++i) {
     JS::ExposeObjectToActiveJS(aScopeChain[i]);
   }
 
   // Compile.
   JS::Rooted<JSFunction*> fun(cx);
+  JS::SourceBufferHolder source(PromiseFlatString(aBody).get(), aBody.Length(),
+                                JS::SourceBufferHolder::NoOwnership);
   if (!JS::CompileFunction(cx, aScopeChain, aOptions,
                            PromiseFlatCString(aName).get(),
                            aArgCount, aArgArray,
-                           PromiseFlatString(aBody).get(),
-                           aBody.Length(), &fun))
+                           source, &fun))
   {
     return NS_ERROR_FAILURE;
   }
 
   *aFunctionObject = JS_GetFunctionObject(fun);
   return NS_OK;
 }
 
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -4862,18 +4862,19 @@ WorkerPrivate::RunExpiredTimeouts(JSCont
       uint32_t lineNo = 0, dummyColumn = 0;
       info->mHandler->GetLocation(&filename, &lineNo, &dummyColumn);
 
       JS::CompileOptions options(aes.cx());
       options.setFileAndLine(filename, lineNo).setNoScriptRval(true);
 
       JS::Rooted<JS::Value> unused(aes.cx());
 
-      if (!JS::Evaluate(aes.cx(), options, script.BeginReading(),
-                        script.Length(), &unused) &&
+      JS::SourceBufferHolder srcBuf(script.BeginReading(), script.Length(),
+                                    JS::SourceBufferHolder::NoOwnership);
+      if (!JS::Evaluate(aes.cx(), options, srcBuf, &unused) &&
           !JS_IsExceptionPending(aCx)) {
         retval = false;
         break;
       }
     } else {
       ErrorResult rv;
       JS::Rooted<JS::Value> ignoredVal(aCx);
       callback->Call(GlobalScope(), info->mHandler->GetArgs(), &ignoredVal, rv,
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -482,18 +482,19 @@ XPCShellEnvironment::EvaluateString(cons
 {
   AutoEntryScript aes(GetGlobalObject(),
                       "ipc XPCShellEnvironment::EvaluateString");
   JSContext* cx = aes.cx();
 
   JS::CompileOptions options(cx);
   options.setFileAndLine("typein", 0);
   JS::Rooted<JSScript*> script(cx);
-  if (!JS_CompileUCScript(cx, aString.get(), aString.Length(), options,
-                          &script))
+  JS::SourceBufferHolder srcBuf(aString.get(), aString.Length(),
+                                JS::SourceBufferHolder::NoOwnership);
+  if (!JS_CompileUCScript(cx, srcBuf, options, &script))
   {
      return false;
   }
 
   if (aResult) {
       aResult->Truncate();
   }
 
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -5170,17 +5170,18 @@ js::TestingFunctionArgumentToScript(JSCo
         size_t len = GetLinearStringLength(linearStr);
         AutoStableStringChars linearChars(cx);
         if (!linearChars.initTwoByte(cx, linearStr))
             return nullptr;
         const char16_t* chars = linearChars.twoByteRange().begin().get();
 
         RootedScript script(cx);
         CompileOptions options(cx);
-        if (!JS::Compile(cx, options, chars, len, &script))
+        SourceBufferHolder source(chars, len, SourceBufferHolder::NoOwnership);
+        if (!JS::Compile(cx, options, source, &script))
             return nullptr;
         return script;
     }
 
     RootedFunction fun(cx, JS_ValueToFunction(cx, v));
     if (!fun)
         return nullptr;
 
--- a/js/src/jsapi-tests/testCompileNonSyntactic.cpp
+++ b/js/src/jsapi-tests/testCompileNonSyntactic.cpp
@@ -79,28 +79,34 @@ testCompile(bool nonSyntactic)
     // Check explicit non-syntactic compilation first to make sure it doesn't
     // modify our options object.
     CHECK(CompileForNonSyntacticScope(cx, options, buf, &script));
     CHECK_EQUAL(script->hasNonSyntacticScope(), true);
 
     CHECK(CompileForNonSyntacticScope(cx, options, src, length, &script));
     CHECK_EQUAL(script->hasNonSyntacticScope(), true);
 
-    CHECK(CompileForNonSyntacticScope(cx, options, src_16, length, &script));
-    CHECK_EQUAL(script->hasNonSyntacticScope(), true);
+    {
+        JS::SourceBufferHolder srcBuf(src_16, length, JS::SourceBufferHolder::NoOwnership);
+        CHECK(CompileForNonSyntacticScope(cx, options, srcBuf, &script));
+        CHECK_EQUAL(script->hasNonSyntacticScope(), true);
+    }
 
 
     CHECK(Compile(cx, options, buf, &script));
     CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
 
     CHECK(Compile(cx, options, src, length, &script));
     CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
 
-    CHECK(Compile(cx, options, src_16, length, &script));
-    CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
+    {
+        JS::SourceBufferHolder srcBuf(src_16, length, JS::SourceBufferHolder::NoOwnership);
+        CHECK(Compile(cx, options, srcBuf, &script));
+        CHECK_EQUAL(script->hasNonSyntacticScope(), nonSyntactic);
+    }
 
 
     options.forceAsync = true;
     OffThreadTask task;
     OffThreadToken* token;
 
     CHECK(CompileOffThread(cx, options, src_16, length,
                            task.OffThreadCallback, &task));
--- a/js/src/jsapi-tests/testErrorLineOfContext.cpp
+++ b/js/src/jsapi-tests/testErrorLineOfContext.cpp
@@ -35,17 +35,18 @@ eval(const char16_t* chars, size_t len, 
 {
     JS::RealmOptions globalOptions;
     JS::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
 						   JS::FireOnNewGlobalHook, globalOptions));
     CHECK(global);
 
     JSAutoRealm ar(cx, global);
     JS::CompileOptions options(cx);
-    return JS::Evaluate(cx, options, chars, len, rval);
+    JS::SourceBufferHolder srcBuf(chars, len, JS::SourceBufferHolder::NoOwnership);
+    return JS::Evaluate(cx, options, srcBuf, rval);
 }
 
 template<size_t N>
 bool
 testLineOfContextHasNoLineTerminator(const char16_t (&chars)[N], char16_t expectedLast)
 {
     JS::RootedValue rval(cx);
     CHECK(!eval(chars, N - 1, &rval));
--- a/js/src/jsapi-tests/testJSEvaluateScript.cpp
+++ b/js/src/jsapi-tests/testJSEvaluateScript.cpp
@@ -12,18 +12,19 @@ BEGIN_TEST(testJSEvaluateScript)
     CHECK(obj);
 
     static const char16_t src[] = u"var x = 5;";
 
     JS::RootedValue retval(cx);
     JS::CompileOptions opts(cx);
     JS::AutoObjectVector scopeChain(cx);
     CHECK(scopeChain.append(obj));
+    JS::SourceBufferHolder srcBuf(src, ArrayLength(src) - 1, JS::SourceBufferHolder::NoOwnership);
     CHECK(JS::Evaluate(cx, scopeChain, opts.setFileAndLine(__FILE__, __LINE__),
-                       src, ArrayLength(src) - 1, &retval));
+                       srcBuf, &retval));
 
     bool hasProp = true;
     CHECK(JS_AlreadyHasOwnProperty(cx, obj, "x", &hasProp));
     CHECK(hasProp);
 
     hasProp = false;
     CHECK(JS_HasProperty(cx, global, "x", &hasProp));
     CHECK(!hasProp);
--- a/js/src/jsapi-tests/testMutedErrors.cpp
+++ b/js/src/jsapi-tests/testMutedErrors.cpp
@@ -49,17 +49,18 @@ eval(const char* asciiChars, bool mutedE
     JSAutoRealm ar(cx, global);
     CHECK(JS::InitRealmStandardClasses(cx));
 
 
     JS::CompileOptions options(cx);
     options.setMutedErrors(mutedErrors)
            .setFileAndLine("", 0);
 
-    return JS::Evaluate(cx, options, chars.get(), len, rval);
+    JS::SourceBufferHolder srcBuf(chars.get(), len, JS::SourceBufferHolder::NoOwnership);
+    return JS::Evaluate(cx, options, srcBuf, rval);
 }
 
 bool
 testOuter(const char* asciiChars)
 {
     CHECK(testInner(asciiChars, false));
     CHECK(testInner(asciiChars, true));
     return true;
--- a/js/src/jsapi-tests/testScriptObject.cpp
+++ b/js/src/jsapi-tests/testScriptObject.cpp
@@ -67,37 +67,40 @@ BEGIN_FIXTURE_TEST(ScriptObjectFixture, 
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScriptForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript)
 {
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, __LINE__);
     JS::RootedScript script(cx);
-    CHECK(JS_CompileUCScript(cx, uc_code, code_size, options, &script));
+    JS::SourceBufferHolder srcBuf(uc_code, code_size, JS::SourceBufferHolder::NoOwnership);
+    CHECK(JS_CompileUCScript(cx, srcBuf, options, &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::RootedScript script(cx);
-    CHECK(JS_CompileUCScript(cx, uc_code, 0, options, &script));
+    JS::SourceBufferHolder srcBuf(uc_code, 0, JS::SourceBufferHolder::NoOwnership);
+    CHECK(JS_CompileUCScript(cx, srcBuf, options, &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::RootedScript script(cx);
-    CHECK(JS_CompileUCScript(cx, uc_code, code_size, options, &script));
+    JS::SourceBufferHolder srcBuf(uc_code, code_size, JS::SourceBufferHolder::NoOwnership);
+    CHECK(JS_CompileUCScript(cx, srcBuf, options, &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";
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4004,35 +4004,28 @@ Compile(JSContext* cx, const ReadOnlyCom
     CHECK_REQUEST(cx);
 
     script.set(frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind, options, srcBuf));
     return !!script;
 }
 
 static bool
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
-        const char16_t* chars, size_t length, MutableHandleScript script)
-{
-    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-    return ::Compile(cx, options, srcBuf, script);
-}
-
-static bool
-Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         const char* bytes, size_t length, MutableHandleScript script)
 {
-    UniqueTwoByteChars chars;
+    char16_t* chars;
     if (options.utf8)
-        chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
+        chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
     else
-        chars.reset(InflateString(cx, bytes, length));
+        chars = InflateString(cx, bytes, length);
     if (!chars)
         return false;
 
-    return ::Compile(cx, options, chars.get(), length, script);
+    SourceBufferHolder source(chars, length, SourceBufferHolder::GiveOwnership);
+    return ::Compile(cx, options, source, script);
 }
 
 static bool
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         FILE* fp, MutableHandleScript script)
 {
     FileContents buffer(cx);
     if (!ReadCompleteFile(cx, fp, buffer))
@@ -4064,23 +4057,16 @@ bool
 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
             const char* bytes, size_t length, JS::MutableHandleScript script)
 {
     return ::Compile(cx, options, bytes, length, script);
 }
 
 bool
 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
-            const char16_t* chars, size_t length, JS::MutableHandleScript script)
-{
-    return ::Compile(cx, options, chars, length, script);
-}
-
-bool
-JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
             FILE* file, JS::MutableHandleScript script)
 {
     return ::Compile(cx, options, file, script);
 }
 
 bool
 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
             const char* filename, JS::MutableHandleScript script)
@@ -4103,26 +4089,16 @@ JS::CompileForNonSyntacticScope(JSContex
 {
     CompileOptions options(cx, optionsArg);
     options.setNonSyntacticScope(true);
     return ::Compile(cx, options, bytes, length, script);
 }
 
 bool
 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
-                                const char16_t* chars, size_t length,
-                                JS::MutableHandleScript script)
-{
-    CompileOptions options(cx, optionsArg);
-    options.setNonSyntacticScope(true);
-    return ::Compile(cx, options, chars, length, script);
-}
-
-bool
-JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
                                 FILE* file, JS::MutableHandleScript script)
 {
     CompileOptions options(cx, optionsArg);
     options.setNonSyntacticScope(true);
     return ::Compile(cx, options, file, script);
 }
 
 bool
@@ -4356,20 +4332,20 @@ JS::CancelMultiOffThreadScriptsDecoder(J
 JS_PUBLIC_API(bool)
 JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
                  const JS::CompileOptions& options, MutableHandleScript script)
 {
     return ::Compile(cx, options, ascii, length, script);
 }
 
 JS_PUBLIC_API(bool)
-JS_CompileUCScript(JSContext* cx, const char16_t* chars, size_t length,
+JS_CompileUCScript(JSContext* cx, JS::SourceBufferHolder& srcBuf,
                    const JS::CompileOptions& options, MutableHandleScript script)
 {
-    return ::Compile(cx, options, chars, length, script);
+    return ::Compile(cx, options, srcBuf, script);
 }
 
 JS_PUBLIC_API(bool)
 JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, size_t length)
 {
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
@@ -4580,39 +4556,29 @@ JS::CompileFunction(JSContext* cx, AutoO
     return CompileFunction(cx, options, nameAtom, isInvalidName, newSrcBuf, parameterListEnd, env,
                            scope, fun);
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
                     const ReadOnlyCompileOptions& options,
                     const char* name, unsigned nargs, const char* const* argnames,
-                    const char16_t* chars, size_t length, MutableHandleFunction fun)
-{
-    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
+                    const char* bytes, size_t length, MutableHandleFunction fun)
+{
+    char16_t* chars;
+    if (options.utf8)
+        chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
+    else
+        chars = InflateString(cx, bytes, length);
+    if (!chars)
+        return false;
+
+    SourceBufferHolder source(chars, length, SourceBufferHolder::GiveOwnership);
     return CompileFunction(cx, envChain, options, name, nargs, argnames,
-                           srcBuf, fun);
-}
-
-JS_PUBLIC_API(bool)
-JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
-                    const ReadOnlyCompileOptions& options,
-                    const char* name, unsigned nargs, const char* const* argnames,
-                    const char* bytes, size_t length, MutableHandleFunction fun)
-{
-    UniqueTwoByteChars chars;
-    if (options.utf8)
-        chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
-    else
-        chars.reset(InflateString(cx, bytes, length));
-    if (!chars)
-        return false;
-
-    return CompileFunction(cx, envChain, options, name, nargs, argnames,
-                           chars.get(), length, fun);
+                           source, fun);
 }
 
 JS_PUBLIC_API(bool)
 JS::InitScriptSourceElement(JSContext* cx, HandleScript script,
                             HandleObject element, HandleString elementAttrName)
 {
     MOZ_ASSERT(cx);
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
@@ -4781,25 +4747,16 @@ Evaluate(JSContext* cx, AutoObjectVector
 {
     RootedObject env(cx);
     RootedScope scope(cx);
     if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope))
         return false;
     return ::Evaluate(cx, scope->kind(), env, optionsArg, srcBuf, rval);
 }
 
-static bool
-Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
-         const char16_t* chars, size_t length, MutableHandleValue rval)
-{
-  SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-  RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
-  return ::Evaluate(cx, ScopeKind::Global, globalLexical, optionsArg, srcBuf, rval);
-}
-
 extern JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
              const char* bytes, size_t length, MutableHandleValue rval)
 {
     char16_t* chars;
     if (options.utf8)
         chars = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get();
     else
@@ -4841,31 +4798,16 @@ JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
              SourceBufferHolder& srcBuf, MutableHandleValue rval)
 {
     return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval);
 }
 
 JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
-             const char16_t* chars, size_t length, MutableHandleValue rval)
-{
-    return ::Evaluate(cx, optionsArg, chars, length, rval);
-}
-
-JS_PUBLIC_API(bool)
-JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
-             const char16_t* chars, size_t length, MutableHandleValue rval)
-{
-    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-    return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval);
-}
-
-JS_PUBLIC_API(bool)
-JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
              const char* filename, MutableHandleValue rval)
 {
     return ::Evaluate(cx, optionsArg, filename, rval);
 }
 
 JS_PUBLIC_API(JS::ModuleResolveHook)
 JS::GetModuleResolveHook(JSRuntime* rt)
 {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3181,17 +3181,17 @@ extern JS_PUBLIC_API(bool)
 JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
                  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, const char16_t* chars, size_t length,
+JS_CompileUCScript(JSContext* cx, JS::SourceBufferHolder& srcBuf,
                    const JS::CompileOptions& options,
                    JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(JSObject*)
 JS_GetGlobalFromScript(JSScript* script);
 
 extern JS_PUBLIC_API(const char*)
 JS_GetScriptFilename(JSScript* script);
@@ -3596,40 +3596,32 @@ Compile(JSContext* cx, const ReadOnlyCom
         SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         const char* bytes, size_t length, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
-        const char16_t* chars, size_t length, JS::MutableHandleScript script);
-
-extern JS_PUBLIC_API(bool)
-Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         FILE* file, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         const char* filename, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
                             SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
                             const char* bytes, size_t length, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
-                            const char16_t* chars, size_t length, JS::MutableHandleScript script);
-
-extern JS_PUBLIC_API(bool)
-CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
                             FILE* file, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
                             const char* filename, JS::MutableHandleScript script);
 
 extern JS_PUBLIC_API(bool)
 CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);
@@ -3710,25 +3702,16 @@ CancelMultiOffThreadScriptsDecoder(JSCon
  * 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.
  */
 extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext* cx, AutoObjectVector& envChain,
                 const ReadOnlyCompileOptions& options,
                 const char* name, unsigned nargs, const char* const* argnames,
-                const char16_t* chars, size_t length, JS::MutableHandleFunction fun);
-
-/**
- * Same as above, but taking a SourceBufferHolder for the function body.
- */
-extern JS_PUBLIC_API(bool)
-CompileFunction(JSContext* cx, AutoObjectVector& envChain,
-                const ReadOnlyCompileOptions& options,
-                const char* name, unsigned nargs, const char* const* argnames,
                 SourceBufferHolder& srcBuf, JS::MutableHandleFunction fun);
 
 /**
  * Same as above, but taking a const char * for the function body.
  */
 extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext* cx, AutoObjectVector& envChain,
                 const ReadOnlyCompileOptions& options,
@@ -3833,32 +3816,16 @@ Evaluate(JSContext* cx, const ReadOnlyCo
  * the global object on it; that's implicit.  It needs to contain the other
  * objects that should end up on the script's scope chain.
  */
 extern JS_PUBLIC_API(bool)
 Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options,
          SourceBufferHolder& srcBuf, JS::MutableHandleValue rval);
 
 /**
- * Evaluate the given character buffer in the scope of the current global of cx.
- */
-extern JS_PUBLIC_API(bool)
-Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
-         const char16_t* chars, size_t length, JS::MutableHandleValue rval);
-
-/**
- * As above, but providing an explicit scope chain.  envChain must not include
- * the global object on it; that's implicit.  It needs to contain the other
- * objects that should end up on the script's scope chain.
- */
-extern JS_PUBLIC_API(bool)
-Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options,
-         const char16_t* chars, size_t length, JS::MutableHandleValue rval);
-
-/**
  * Evaluate the given byte buffer in the scope of the current global of cx.
  */
 extern JS_PUBLIC_API(bool)
 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
          const char* bytes, size_t length, JS::MutableHandleValue rval);
 
 /**
  * Evaluate the given file in the scope of the current global of cx.
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1980,20 +1980,22 @@ Evaluate(JSContext* cx, unsigned argc, V
             }
 
             if (loadBytecode) {
                 JS::TranscodeResult rv = JS::DecodeScript(cx, loadBuffer, &script);
                 if (!ConvertTranscodeResultToJSException(cx, rv))
                     return false;
             } else {
                 mozilla::Range<const char16_t> chars = codeChars.twoByteRange();
+                JS::SourceBufferHolder srcBuf(chars.begin().get(), chars.length(),
+                                              JS::SourceBufferHolder::NoOwnership);
                 if (envChain.length() == 0) {
-                    (void) JS::Compile(cx, options, chars.begin().get(), chars.length(), &script);
+                    (void) JS::Compile(cx, options, srcBuf, &script);
                 } else {
-                    (void) JS::CompileForNonSyntacticScope(cx, options, chars.begin().get(), chars.length(), &script);
+                    (void) JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script);
                 }
             }
 
             if (!script)
                 return false;
         }
 
         if (displayURL && !script->scriptSource()->hasDisplayURL()) {
@@ -2182,33 +2184,33 @@ Run(JSContext* cx, unsigned argc, Value*
     str = FileAsString(cx, str);
     if (!str)
         return false;
 
     AutoStableStringChars chars(cx);
     if (!chars.initTwoByte(cx, str))
         return false;
 
-    const char16_t* ucbuf = chars.twoByteRange().begin().get();
-    size_t buflen = str->length();
+    JS::SourceBufferHolder srcBuf(chars.twoByteRange().begin().get(), str->length(),
+                                  JS::SourceBufferHolder::NoOwnership);
 
     RootedScript script(cx);
     int64_t startClock = PRMJ_Now();
     {
         /* FIXME: This should use UTF-8 (bug 987069). */
         JSAutoByteString filename(cx, str);
         if (!filename)
             return false;
 
         JS::CompileOptions options(cx);
         options.setIntroductionType("js shell run")
                .setFileAndLine(filename.ptr(), 1)
                .setIsRunOnce(true)
                .setNoScriptRval(true);
-        if (!JS_CompileUCScript(cx, ucbuf, buflen, options, &script))
+        if (!JS_CompileUCScript(cx, srcBuf, options, &script))
             return false;
     }
 
     if (!JS_ExecuteScript(cx, script))
         return false;
 
     int64_t endClock = PRMJ_Now();
 
@@ -3544,17 +3546,18 @@ EvalInContext(JSContext* cx, unsigned ar
         sobj = ToWindowIfWindowProxy(sobj);
 
         if (!(sobj->getClass()->flags & JSCLASS_IS_GLOBAL)) {
             JS_ReportErrorASCII(cx, "Invalid scope argument to evalcx");
             return false;
         }
         JS::CompileOptions opts(cx);
         opts.setFileAndLine(filename.get(), lineno);
-        if (!JS::Evaluate(cx, opts, src, srclen, args.rval())) {
+        JS::SourceBufferHolder srcBuf(src, srclen, JS::SourceBufferHolder::NoOwnership);
+        if (!JS::Evaluate(cx, opts, srcBuf, args.rval())) {
             return false;
         }
     }
 
     if (!cx->compartment()->wrap(cx, args.rval()))
         return false;
 
     return true;
@@ -3647,17 +3650,19 @@ WorkerMain(WorkerInput* input)
         JSAutoRealmAllowCCW ar(cx, global);
 
         JS::CompileOptions options(cx);
         options.setFileAndLine("<string>", 1)
                .setIsRunOnce(true);
 
         AutoReportException are(cx);
         RootedScript script(cx);
-        if (!JS::Compile(cx, options, input->chars.get(), input->length, &script))
+        JS::SourceBufferHolder srcBuf(input->chars.get(), input->length,
+                                      JS::SourceBufferHolder::NoOwnership);
+        if (!JS::Compile(cx, options, srcBuf, &script))
             break;
         RootedValue result(cx);
         JS_ExecuteScript(cx, script, &result);
     } while (0);
 
     KillWatchdog(cx);
     JS_SetGrayGCRootsTracer(cx, nullptr, nullptr);
 }
@@ -4233,18 +4238,20 @@ Compile(JSContext* cx, unsigned argc, Va
         return false;
 
     JS::CompileOptions options(cx);
     options.setIntroductionType("js shell compile")
            .setFileAndLine("<string>", 1)
            .setIsRunOnce(true)
            .setNoScriptRval(true);
     RootedScript script(cx);
-    const char16_t* chars = stableChars.twoByteRange().begin().get();
-    bool ok = JS_CompileUCScript(cx, chars, scriptContents->length(), options, &script);
+    JS::SourceBufferHolder srcBuf(stableChars.twoByteRange().begin().get(),
+                                  scriptContents->length(),
+                                  JS::SourceBufferHolder::NoOwnership);
+    bool ok = JS_CompileUCScript(cx, srcBuf, options, &script);
     args.rval().setUndefined();
     return ok;
 }
 
 static bool
 ParseModule(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -6681,25 +6688,26 @@ EntryPoints(JSContext* cx, unsigned argc
         if (!code.isUndefined()) {
             RootedString codeString(cx, ToString(cx, code));
             if (!codeString || !codeString->ensureFlat(cx))
                 return false;
 
             AutoStableStringChars stableChars(cx);
             if (!stableChars.initTwoByte(cx, codeString))
                 return false;
-            const char16_t* chars = stableChars.twoByteRange().begin().get();
-            size_t length = codeString->length();
+            JS::SourceBufferHolder srcBuf(stableChars.twoByteRange().begin().get(),
+                                          codeString->length(),
+                                          JS::SourceBufferHolder::NoOwnership);
 
             CompileOptions options(cx);
             options.setIntroductionType("entryPoint eval")
                    .setFileAndLine("entryPoint eval", 1);
 
             js::shell::ShellAutoEntryMonitor sarep(cx);
-            if (!JS::Evaluate(cx, options, chars, length, &dummy))
+            if (!JS::Evaluate(cx, options, srcBuf, &dummy))
                 return false;
             return sarep.buildResult(cx, args.rval());
         }
     }
 
     JS_ReportErrorASCII(cx, "bad 'params' object");
     return false;
 }
--- a/js/xpconnect/loader/ChromeScriptLoader.cpp
+++ b/js/xpconnect/loader/ChromeScriptLoader.cpp
@@ -138,17 +138,19 @@ AsyncScriptCompiler::StartCompile(JSCont
             return false;
         }
 
         NS_ADDREF(this);
         return true;
     }
 
     Rooted<JSScript*> script(aCx);
-    if (!JS::Compile(aCx, mOptions, mScriptText.get(), mScriptLength, &script)) {
+    JS::SourceBufferHolder srcBuf(mScriptText.get(), mScriptLength,
+                                  JS::SourceBufferHolder::NoOwnership);
+    if (!JS::Compile(aCx, mOptions, srcBuf, &script)) {
         return false;
     }
 
     Finish(aCx, script);
     return true;
 }
 
 NS_IMETHODIMP
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1844,18 +1844,19 @@ xpc::EvalInSandbox(JSContext* cx, Handle
         // This is clearly Gecko-specific and not in any spec.
         mozilla::dom::AutoEntryScript aes(priv, "XPConnect sandbox evaluation");
         JSContext* sandcx = aes.cx();
         JSAutoRealmAllowCCW ar(sandcx, sandbox);
 
         JS::CompileOptions options(sandcx);
         options.setFileAndLine(filenameBuf.get(), lineNo);
         MOZ_ASSERT(JS_IsGlobalObject(sandbox));
-        ok = JS::Evaluate(sandcx, options,
-                          PromiseFlatString(source).get(), source.Length(), &v);
+        JS::SourceBufferHolder buffer(PromiseFlatString(source).get(), source.Length(),
+                                      JS::SourceBufferHolder::NoOwnership);
+        ok = JS::Evaluate(sandcx, options, buffer, &v);
 
         // If the sandbox threw an exception, grab it off the context.
         if (aes.HasException()) {
             if (!aes.StealException(&exn)) {
                 return NS_ERROR_OUT_OF_MEMORY;
             }
         }
     }