Merge inbound to mozilla-central. a=merge
authorshindli <shindli@mozilla.com>
Wed, 16 May 2018 21:31:38 +0300
changeset 418546 d5b463283f3983c0e7c9d78cb8559f89b52e1cd3
parent 418545 a35fc68a24710f1fe7ed3a7a267f0f8158a9819a (current diff)
parent 418482 eac1b2073bf4985fa4d521bb952cc1305813d6f3 (diff)
child 418547 11857580f5e11b0cd8429ce7522782ddcc2ecccd
child 418571 1800b8895c08bc0c60302775dc0a4b5ea4deb310
child 418629 d24d69240fc260f5e8d7d9ad84671f59128cae36
push id103323
push usershindli@mozilla.com
push dateWed, 16 May 2018 18:54:02 +0000
treeherdermozilla-inbound@11857580f5e1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone62.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
Merge inbound to mozilla-central. a=merge
dom/media/test/test_streams_element_capture_createObjectURL.html
old-configure.in
--- a/browser/app/LauncherProcessWin.cpp
+++ b/browser/app/LauncherProcessWin.cpp
@@ -213,12 +213,17 @@ LauncherMain(int argc, wchar_t* argv[])
 
   if (!PostCreationSetup(process.get(), mainThread.get(), isSafeMode.value()) ||
       ::ResumeThread(mainThread.get()) == static_cast<DWORD>(-1)) {
     ShowError();
     ::TerminateProcess(process.get(), 1);
     return 1;
   }
 
+  // Keep the current process around until the callback process has created
+  // its message queue, to avoid the launched process's windows being forced
+  // into the background.
+  ::WaitForInputIdle(process.get(), kWaitForInputIdleTimeoutMS);
+
   return 0;
 }
 
 } // namespace mozilla
--- a/browser/components/sessionstore/test/browser.ini
+++ b/browser/components/sessionstore/test/browser.ini
@@ -162,16 +162,17 @@ skip-if = true
 [browser_491577.js]
 [browser_495495.js]
 [browser_500328.js]
 [browser_514751.js]
 [browser_522375.js]
 [browser_522545.js]
 skip-if = true # Bug 1380968
 [browser_524745.js]
+skip-if = (os == "win" && os_version == "10.0" && !ccov) # Bug 1418627
 [browser_528776.js]
 [browser_579868.js]
 [browser_579879.js]
 skip-if = (os == 'linux' && e10s && (debug||asan)) # Bug 1234404
 [browser_581937.js]
 [browser_586147.js]
 [browser_586068-apptabs.js]
 [browser_586068-apptabs_ondemand.js]
--- a/browser/installer/windows/nsis/installer.nsi
+++ b/browser/installer/windows/nsis/installer.nsi
@@ -888,28 +888,28 @@ Function LaunchApp
 !ifndef DEV_EDITION
   ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
 !endif
 
   ClearErrors
   ${GetParameters} $0
   ${GetOptions} "$0" "/UAC:" $1
   ${If} ${Errors}
-    Exec "$\"$INSTDIR\${FileMainEXE}$\""
+    ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\""
   ${Else}
     GetFunctionAddress $0 LaunchAppFromElevatedProcess
     UAC::ExecCodeSegment $0
   ${EndIf}
 FunctionEnd
 
 Function LaunchAppFromElevatedProcess
   ; Set our current working directory to the application's install directory
   ; otherwise the 7-Zip temp directory will be in use and won't be deleted.
   SetOutPath "$INSTDIR"
-  Exec "$\"$INSTDIR\${FileMainEXE}$\""
+  ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\""
 FunctionEnd
 
 ################################################################################
 # Language
 
 !insertmacro MOZ_MUI_LANGUAGE 'baseLocale'
 !verbose push
 !verbose 3
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -1656,37 +1656,37 @@ Function LaunchApp
 
   ; Set the current working directory to the installation directory
   SetOutPath "$INSTDIR"
   ClearErrors
   ${GetParameters} $0
   ${GetOptions} "$0" "/UAC:" $1
   ${If} ${Errors}
     ${If} $CheckboxCleanupProfile == 1
-      Exec "$\"$INSTDIR\${FileMainEXE}$\" -reset-profile -migration"
+      ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" -reset-profile -migration"
     ${Else}
-      Exec "$\"$INSTDIR\${FileMainEXE}$\""
+      ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\""
     ${EndIf}
   ${Else}
     StrCpy $R1 $CheckboxCleanupProfile
     GetFunctionAddress $0 LaunchAppFromElevatedProcess
     UAC::ExecCodeSegment $0
   ${EndIf}
 
   StrCpy $AppLaunchWaitTickCount 0
   ${NSD_CreateTimer} WaitForAppLaunch ${AppLaunchWaitIntervalMS}
 FunctionEnd
 
 Function LaunchAppFromElevatedProcess
   ; Set the current working directory to the installation directory
   SetOutPath "$INSTDIR"
   ${If} $R1 == 1
-    Exec "$\"$INSTDIR\${FileMainEXE}$\" -reset-profile -migration"
+    ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" -reset-profile -migration"
   ${Else}
-    Exec "$\"$INSTDIR\${FileMainEXE}$\""
+    ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\""
   ${EndIf}
 FunctionEnd
 
 Function WaitForAppLaunch
   FindWindow $0 "${MainWindowClass}"
   FindWindow $1 "${DialogWindowClass}"
   ${If} $0 <> 0
   ${OrIf} $1 <> 0
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -665,17 +665,17 @@ function prompt(aBrowser, aRequest) {
           let constraints = { video: { mediaSource: type, deviceId: {exact: deviceId } } };
           chromeWin.navigator.mediaDevices.getUserMedia(constraints).then(stream => {
             if (video.deviceId != deviceId) {
               // The user has selected a different device or closed the panel
               // before getUserMedia finished.
               stream.getTracks().forEach(t => t.stop());
               return;
             }
-            video.src = chromeWin.URL.createObjectURL(stream);
+            video.srcObject = stream;
             video.stream = stream;
             doc.getElementById("webRTC-preview").hidden = false;
             video.onloadedmetadata = function(e) {
               video.play();
             };
           });
         };
         menupopup.addEventListener("command", menupopup._commandEventListener);
--- a/devtools/client/webconsole/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/test/mochitest/browser.ini
@@ -336,17 +336,17 @@ subsuite = clipboard
 [browser_webconsole_shows_reqs_from_netmonitor.js]
 [browser_webconsole_shows_reqs_in_netmonitor.js]
 [browser_webconsole_sidebar_object_expand_when_message_pruned.js]
 [browser_webconsole_sourcemap_css.js]
 [browser_webconsole_sourcemap_error.js]
 [browser_webconsole_sourcemap_invalid.js]
 [browser_webconsole_sourcemap_nosource.js]
 [browser_webconsole_split.js]
-skip-if = os == 'win' && !debug # Bug 1454123 disabled on Win for frequent failures
+skip-if = os == 'osx' || (os == 'win' && !debug) # Bug 1454123 disabled on OS X and Win for frequent failures
 [browser_webconsole_split_escape_key.js]
 [browser_webconsole_split_focus.js]
 [browser_webconsole_split_persist.js]
 [browser_webconsole_stacktrace_location_debugger_link.js]
 [browser_webconsole_stacktrace_location_scratchpad_link.js]
 [browser_webconsole_strict_mode_errors.js]
 [browser_webconsole_string.js]
 [browser_webconsole_time_methods.js]
--- a/devtools/shared/heapsnapshot/tests/gtest/DevTools.h
+++ b/devtools/shared/heapsnapshot/tests/gtest/DevTools.h
@@ -89,17 +89,17 @@ struct DevTools : public ::testing::Test
     /* Create the global object. */
     JS::RootedObject newGlobal(cx);
     JS::CompartmentOptions options;
     newGlobal = JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
                                    JS::FireOnNewGlobalHook, options);
     if (!newGlobal)
       return nullptr;
 
-    JSAutoCompartment ac(cx, newGlobal);
+    JSAutoRealm ar(cx, newGlobal);
 
     /* Populate the global object with the standard globals, like Object and
        Array. */
     if (!JS_InitStandardClasses(cx, newGlobal))
       return nullptr;
 
     return newGlobal;
   }
--- a/devtools/shared/heapsnapshot/tests/gtest/DoesCrossCompartmentBoundaries.cpp
+++ b/devtools/shared/heapsnapshot/tests/gtest/DoesCrossCompartmentBoundaries.cpp
@@ -13,17 +13,17 @@ DEF_TEST(DoesCrossCompartmentBoundaries,
     JS::RootedObject newGlobal(cx, JS_NewGlobalObject(cx,
                                                       getGlobalClass(),
                                                       nullptr,
                                                       JS::FireOnNewGlobalHook,
                                                       options));
     ASSERT_TRUE(newGlobal);
     JSCompartment* newCompartment = nullptr;
     {
-      JSAutoCompartment ac(cx, newGlobal);
+      JSAutoRealm ar(cx, newGlobal);
       ASSERT_TRUE(JS_InitStandardClasses(cx, newGlobal));
       newCompartment = js::GetContextCompartment(cx);
     }
     ASSERT_TRUE(newCompartment);
     ASSERT_NE(newCompartment, compartment);
 
     // Our set of target compartments is both the old and new compartments.
     JS::CompartmentSet targetCompartments;
--- a/devtools/shared/heapsnapshot/tests/gtest/DoesntCrossCompartmentBoundaries.cpp
+++ b/devtools/shared/heapsnapshot/tests/gtest/DoesntCrossCompartmentBoundaries.cpp
@@ -13,17 +13,17 @@ DEF_TEST(DoesntCrossCompartmentBoundarie
     JS::RootedObject newGlobal(cx, JS_NewGlobalObject(cx,
                                                       getGlobalClass(),
                                                       nullptr,
                                                       JS::FireOnNewGlobalHook,
                                                       options));
     ASSERT_TRUE(newGlobal);
     JSCompartment* newCompartment = nullptr;
     {
-      JSAutoCompartment ac(cx, newGlobal);
+      JSAutoRealm ar(cx, newGlobal);
       ASSERT_TRUE(JS_InitStandardClasses(cx, newGlobal));
       newCompartment = js::GetContextCompartment(cx);
     }
     ASSERT_TRUE(newCompartment);
     ASSERT_NE(newCompartment, compartment);
 
     // Our set of target compartments is only the pre-existing compartment and
     // does not include the new compartment.
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -210,17 +210,17 @@ ChromeUtils::ShallowClone(GlobalObject& 
       return;
     }
 
     if (js::IsScriptedProxy(obj)) {
       JS_ReportErrorASCII(cx, "Shallow cloning a proxy object is not allowed");
       return;
     }
 
-    JSAutoCompartment ac(cx, obj);
+    JSAutoRealm ar(cx, obj);
 
     if (!JS_Enumerate(cx, obj, &ids) ||
         !values.reserve(ids.length())) {
       return;
     }
 
     JS::Rooted<JS::PropertyDescriptor> desc(cx);
     JS::RootedId id(cx);
@@ -233,24 +233,24 @@ ChromeUtils::ShallowClone(GlobalObject& 
         continue;
       }
       values.infallibleAppend(desc.value());
     }
   }
 
   JS::RootedObject obj(cx);
   {
-    Maybe<JSAutoCompartment> ac;
+    Maybe<JSAutoRealm> ar;
     if (aTarget) {
       JS::RootedObject target(cx, js::CheckedUnwrap(aTarget));
       if (!target) {
         js::ReportAccessDenied(cx);
         return;
       }
-      ac.emplace(cx, target);
+      ar.emplace(cx, target);
     }
 
     obj = JS_NewPlainObject(cx);
     if (!obj) {
       return;
     }
 
     JS::RootedValue value(cx);
@@ -476,17 +476,17 @@ namespace module_getter {
     nsresult rv = moduleloader->Import(aCx, uri, &moduleGlobal, &moduleExports);
     if (NS_FAILED(rv)) {
       Throw(aCx, rv);
       return false;
     }
 
     JS::RootedValue value(aCx);
     {
-      JSAutoCompartment ac(aCx, moduleExports);
+      JSAutoRealm ar(aCx, moduleExports);
 
       if (!JS_GetPropertyById(aCx, moduleExports, id, &value)) {
         return false;
       }
     }
 
     if (!JS_WrapValue(aCx, &value) ||
         !JS_DefinePropertyById(aCx, thisObj, id, value,
@@ -723,21 +723,21 @@ ChromeUtils::CreateError(const GlobalObj
   });
 
   JS::RootedObject retVal(cx);
   {
     JS::RootedString fileName(cx, JS_GetEmptyString(cx));
     uint32_t line = 0;
     uint32_t column = 0;
 
-    Maybe<JSAutoCompartment> ac;
+    Maybe<JSAutoRealm> ar;
     JS::RootedObject stack(cx);
     if (aStack) {
       stack = UncheckedUnwrap(aStack);
-      ac.emplace(cx, stack);
+      ar.emplace(cx, stack);
 
       if (JS::GetSavedFrameLine(cx, stack, &line) != JS::SavedFrameResult::Ok ||
           JS::GetSavedFrameColumn(cx, stack, &column) != JS::SavedFrameResult::Ok ||
           JS::GetSavedFrameSource(cx, stack, &fileName) != JS::SavedFrameResult::Ok) {
         return;
       }
     }
 
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -769,49 +769,49 @@ CustomElementRegistry::Define(const nsAS
   nsAutoPtr<LifecycleCallbacks> callbacksHolder(new LifecycleCallbacks());
   nsTArray<RefPtr<nsAtom>> observedAttributes;
   { // Set mIsCustomDefinitionRunning.
     /**
      * 9. Set this CustomElementRegistry's element definition is running flag.
      */
     AutoSetRunningFlag as(this);
 
-    { // Enter constructor's compartment.
+    { // Enter constructor's realm.
       /**
        * 10.1. Let prototype be Get(constructor, "prototype"). Rethrow any exceptions.
        */
-      JSAutoCompartment ac(cx, constructor);
+      JSAutoRealm ar(cx, constructor);
       // The .prototype on the constructor passed could be an "expando" of a
       // wrapper. So we should get it from wrapper instead of the underlying
       // object.
       if (!JS_GetProperty(cx, constructor, "prototype", &constructorPrototype)) {
         aRv.StealExceptionFromJSContext(cx);
         return;
       }
 
       /**
        * 10.2. If Type(prototype) is not Object, then throw a TypeError exception.
        */
       if (!constructorPrototype.isObject()) {
         aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("constructor.prototype"));
         return;
       }
-    } // Leave constructor's compartment.
+    } // Leave constructor's realm.
 
     JS::Rooted<JSObject*> constructorProtoUnwrapped(
       cx, js::CheckedUnwrap(&constructorPrototype.toObject()));
     if (!constructorProtoUnwrapped) {
       // If the caller's compartment does not have permission to access the
       // unwrapped prototype then throw.
       aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
       return;
     }
 
     { // Enter constructorProtoUnwrapped's compartment
-      JSAutoCompartment ac(cx, constructorProtoUnwrapped);
+      JSAutoRealm ar(cx, constructorProtoUnwrapped);
 
       /**
        * 10.3. Let lifecycleCallbacks be a map with the four keys
        *       "connectedCallback", "disconnectedCallback", "adoptedCallback", and
        *       "attributeChangedCallback", each of which belongs to an entry whose
        *       value is null.
        * 10.4. For each of the four keys callbackName in lifecycleCallbacks:
        *       1. Let callbackValue be Get(prototype, callbackName). Rethrow any
@@ -842,18 +842,18 @@ CustomElementRegistry::Define(const nsAS
        *       1. Let observedAttributesIterable be Get(constructor,
        *          "observedAttributes"). Rethrow any exceptions.
        *       2. If observedAttributesIterable is not undefined, then set
        *          observedAttributes to the result of converting
        *          observedAttributesIterable to a sequence<DOMString>. Rethrow
        *          any exceptions from the conversion.
        */
       if (callbacksHolder->mAttributeChangedCallback.WasPassed()) {
-        // Enter constructor's compartment.
-        JSAutoCompartment ac(cx, constructor);
+        // Enter constructor's realm.
+        JSAutoRealm ar(cx, constructor);
         JS::Rooted<JS::Value> observedAttributesIterable(cx);
 
         if (!JS_GetProperty(cx, constructor, "observedAttributes",
                             &observedAttributesIterable)) {
           aRv.StealExceptionFromJSContext(cx);
           return;
         }
 
@@ -892,17 +892,17 @@ CustomElementRegistry::Define(const nsAS
             }
 
             if (!observedAttributes.AppendElement(NS_Atomize(attrStr))) {
               aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
               return;
             }
           }
         }
-      } // Leave constructor's compartment.
+      } // Leave constructor's realm.
     } // Leave constructorProtoUnwrapped's compartment.
   } // Unset mIsCustomDefinitionRunning
 
   /**
    * 11. Let definition be a new custom element definition with name name,
    *     local name localName, constructor constructor, prototype prototype,
    *     observed attributes observedAttributes, and lifecycle callbacks
    *     lifecycleCallbacks.
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3679,21 +3679,21 @@ Element::Animate(const Nullable<ElementO
   RefPtr<KeyframeEffect> effect =
     KeyframeEffect::Constructor(global, aTarget, aKeyframes, aOptions,
                                 aError);
   if (aError.Failed()) {
     return nullptr;
   }
 
   // Animation constructor follows the standard Xray calling convention and
-  // needs to be called in the target element's compartment.
-  Maybe<JSAutoCompartment> ac;
+  // needs to be called in the target element's realm.
+  Maybe<JSAutoRealm> ar;
   if (js::GetContextCompartment(aContext) !=
       js::GetObjectCompartment(ownerGlobal->GetGlobalJSObject())) {
-    ac.emplace(aContext, ownerGlobal->GetGlobalJSObject());
+    ar.emplace(aContext, ownerGlobal->GetGlobalJSObject());
   }
 
   AnimationTimeline* timeline = referenceElement->OwnerDoc()->Timeline();
   RefPtr<Animation> animation =
     Animation::Constructor(global, effect,
                            Optional<AnimationTimeline*>(timeline), aError);
   if (aError.Failed()) {
     return nullptr;
--- a/dom/base/IntlUtils.cpp
+++ b/dom/base/IntlUtils.cpp
@@ -83,17 +83,17 @@ IntlUtils::GetDisplayNames(const Sequenc
   }
 
   if (!retVal.isObject()) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   // Return the result as DisplayNameResult.
-  JSAutoCompartment ac(cx, &retVal.toObject());
+  JSAutoRealm ar(cx, &retVal.toObject());
   if (!aResult.Init(cx, retVal)) {
     aError.Throw(NS_ERROR_FAILURE);
   }
 }
 
 void
 IntlUtils::GetLocaleInfo(const Sequence<nsString>& aLocales,
                          LocaleInfo& aResult, ErrorResult& aError)
@@ -130,16 +130,16 @@ IntlUtils::GetLocaleInfo(const Sequence<
   }
 
   if (!retVal.isObject()) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   // Return the result as LocaleInfo.
-  JSAutoCompartment ac(cx, &retVal.toObject());
+  JSAutoRealm ar(cx, &retVal.toObject());
   if (!aResult.Init(cx, retVal)) {
     aError.Throw(NS_ERROR_FAILURE);
   }
 }
 
 } // dom namespace
 } // mozilla namespace
--- a/dom/base/PostMessageEvent.cpp
+++ b/dom/base/PostMessageEvent.cpp
@@ -72,17 +72,17 @@ PostMessageEvent::Run()
   // that's probably better than crashing.
 
   RefPtr<nsGlobalWindowInner> targetWindow;
   if (mTargetWindow->IsClosedOrClosing() ||
       !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
       targetWindow->IsDying())
     return NS_OK;
 
-  JSAutoCompartment ac(cx, targetWindow->GetWrapper());
+  JSAutoRealm ar(cx, targetWindow->GetWrapper());
 
   // Ensure that any origin which might have been provided is the origin of this
   // window's document.  Note that we do this *now* instead of when postMessage
   // is called because the target window might have been navigated to a
   // different location between then and now.  If this check happened when
   // postMessage was called, it would be fairly easy for a malicious webpage to
   // intercept messages intended for another site by carefully timing navigation
   // of the target window so it changed location after postMessage but before
--- a/dom/base/StructuredCloneBlob.cpp
+++ b/dom/base/StructuredCloneBlob.cpp
@@ -33,42 +33,42 @@ StructuredCloneBlob::~StructuredCloneBlo
 StructuredCloneBlob::Constructor(GlobalObject& aGlobal, JS::HandleValue aValue,
                                  JS::HandleObject aTargetGlobal,
                                  ErrorResult& aRv)
 {
   JSContext* cx = aGlobal.Context();
 
   RefPtr<StructuredCloneBlob> holder = StructuredCloneBlob::Create();
 
-  Maybe<JSAutoCompartment> ac;
+  Maybe<JSAutoRealm> ar;
   JS::RootedValue value(cx, aValue);
 
   if (aTargetGlobal) {
     JS::RootedObject targetGlobal(cx, js::CheckedUnwrap(aTargetGlobal));
     if (!targetGlobal) {
       js::ReportAccessDenied(cx);
       aRv.NoteJSContextException(cx);
       return nullptr;
     }
 
-    ac.emplace(cx, targetGlobal);
+    ar.emplace(cx, targetGlobal);
 
     if (!JS_WrapValue(cx, &value)) {
       aRv.NoteJSContextException(cx);
       return nullptr;
     }
   } else if (value.isObject()) {
     JS::RootedObject obj(cx, js::CheckedUnwrap(&value.toObject()));
     if (!obj) {
       js::ReportAccessDenied(cx);
       aRv.NoteJSContextException(cx);
       return nullptr;
     }
 
-    ac.emplace(cx, obj);
+    ar.emplace(cx, obj);
     value = JS::ObjectValue(*obj);
   }
 
   holder->Write(cx, value, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
@@ -82,17 +82,17 @@ StructuredCloneBlob::Deserialize(JSConte
   JS::RootedObject scope(aCx, js::CheckedUnwrap(aTargetScope));
   if (!scope) {
     js::ReportAccessDenied(aCx);
     aRv.NoteJSContextException(aCx);
     return;
   }
 
   {
-    JSAutoCompartment ac(aCx, scope);
+    JSAutoRealm ar(aCx, scope);
 
     Read(xpc::NativeGlobal(scope), aCx, aResult, aRv);
     if (aRv.Failed()) {
       return;
     }
   }
 
   if (!JS_WrapValue(aCx, aResult)) {
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -709,17 +709,17 @@ nsContentPermissionRequestProxy::Allow(J
     for (uint32_t i = 0; i < mPermissionRequests.Length(); ++i) {
       nsCString type = mPermissionRequests[i].type();
 
       AutoJSAPI jsapi;
       jsapi.Init();
 
       JSContext* cx = jsapi.cx();
       JS::Rooted<JSObject*> obj(cx, &aChoices.toObject());
-      JSAutoCompartment ac(cx, obj);
+      JSAutoRealm ar(cx, obj);
 
       JS::Rooted<JS::Value> val(cx);
 
       if (!JS_GetProperty(cx, obj, type.BeginReading(), &val) ||
           !val.isString()) {
         // no setting for the permission type, clear exception and skip it
         jsapi.ClearException();
       } else {
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3118,17 +3118,17 @@ nsContentUtils::SubjectPrincipal()
   JSContext* cx = GetCurrentJSContext();
   if (!cx) {
     MOZ_CRASH("Accessing the Subject Principal without an AutoJSAPI on the stack is forbidden");
   }
 
   JSCompartment *compartment = js::GetContextCompartment(cx);
 
   // When an AutoJSAPI is instantiated, we are in a null compartment until the
-  // first JSAutoCompartment, which is kind of a purgatory as far as permissions
+  // first JSAutoRealm, which is kind of a purgatory as far as permissions
   // go. It would be nice to just hard-abort if somebody does a security check
   // in this purgatory zone, but that would be too fragile, since it could be
   // triggered by random IsCallerChrome() checks 20-levels deep.
   //
   // So we want to return _something_ here - and definitely not the System
   // Principal, since that would make an AutoJSAPI a very dangerous thing to
   // instantiate.
   //
@@ -7066,17 +7066,17 @@ nsContentUtils::IsPatternMatching(nsAStr
 {
   NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)");
 
   AutoJSContext cx;
   AutoDisableJSInterruptCallback disabler(cx);
 
   // We can use the junk scope here, because we're just using it for
   // regexp evaluation, not actual script execution.
-  JSAutoCompartment ac(cx, xpc::UnprivilegedJunkScope());
+  JSAutoRealm ar(cx, xpc::UnprivilegedJunkScope());
 
   // The pattern has to match the entire value.
   aPattern.InsertLiteral(u"^(?:", 0);
   aPattern.AppendLiteral(")$");
 
   JS::Rooted<JSObject*> re(cx,
     JS_NewUCRegExpObject(cx,
                          static_cast<char16_t*>(aPattern.BeginWriting()),
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -2619,17 +2619,17 @@ nsIDocument::IsSynthesized() {
   return synthesized;
 }
 
 bool
 nsDocument::IsShadowDOMEnabled(JSContext* aCx, JSObject* aObject)
 {
   JS::Rooted<JSObject*> obj(aCx, aObject);
 
-  JSAutoCompartment ac(aCx, obj);
+  JSAutoRealm ar(aCx, obj);
   JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, obj));
   nsCOMPtr<nsPIDOMWindowInner> window =
     do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(global));
 
   nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
   if (!doc) {
     return false;
   }
@@ -7087,17 +7087,17 @@ nsIDocument::AdoptNode(nsINode& aAdopted
   JS::Rooted<JSObject*> newScope(cx, nullptr);
   if (!sameDocument) {
     newScope = GetWrapper();
     if (!newScope && GetScopeObject() && GetScopeObject()->GetGlobalJSObject()) {
       // Make sure cx is in a semi-sane compartment before we call WrapNative.
       // It's kind of irrelevant, given that we're passing aAllowWrapping =
       // false, and documents should always insist on being wrapped in an
       // canonical scope. But we try to pass something sane anyway.
-      JSAutoCompartment ac(cx, GetScopeObject()->GetGlobalJSObject());
+      JSAutoRealm ar(cx, GetScopeObject()->GetGlobalJSObject());
       JS::Rooted<JS::Value> v(cx);
       rv = nsContentUtils::WrapNative(cx, this, this, &v,
                                       /* aAllowWrapping = */ false);
       if (rv.Failed())
         return nullptr;
       newScope = &v.toObject();
     }
   }
@@ -9642,17 +9642,17 @@ nsIDocument::GetStateObject(nsIVariant**
   // current state object.
 
   if (!mStateObjectCached && mStateObjectContainer) {
     AutoJSContext cx;
     nsIGlobalObject* sgo = GetScopeObject();
     NS_ENSURE_TRUE(sgo, NS_ERROR_UNEXPECTED);
     JS::Rooted<JSObject*> global(cx, sgo->GetGlobalJSObject());
     NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     mStateObjectContainer->
       DeserializeToVariant(cx, getter_AddRefs(mStateObjectCached));
   }
 
   NS_IF_ADDREF(*aState = mStateObjectCached);
   return NS_OK;
 }
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -1893,17 +1893,17 @@ nsFrameLoader::SetOwnerContent(Element* 
   }
   mOwnerContent = aContent;
 
   AutoJSAPI jsapi;
   jsapi.Init();
 
   JS::RootedObject wrapper(jsapi.cx(), GetWrapper());
   if (wrapper) {
-    JSAutoCompartment ac(jsapi.cx(), wrapper);
+    JSAutoRealm ar(jsapi.cx(), wrapper);
     IgnoredErrorResult rv;
     ReparentWrapper(jsapi.cx(), wrapper, rv);
     Unused << NS_WARN_IF(rv.Failed());
   }
 
   if (RenderFrameParent* rfp = GetCurrentRenderFrame()) {
     rfp->OwnerContentChanged(aContent);
   }
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -1018,19 +1018,19 @@ nsFrameMessageManager::GetInitialProcess
                                              ErrorResult& aError)
 {
   MOZ_ASSERT(mIsProcessManager);
   MOZ_ASSERT_IF(mChrome, IsBroadcaster());
 
   JS::RootedValue init(aCx, mInitialProcessData);
   if (mChrome && init.isUndefined()) {
     // We create the initial object in the junk scope. If we created it in a
-    // normal compartment, that compartment would leak until shutdown.
+    // normal realm, that realm would leak until shutdown.
     JS::RootedObject global(aCx, xpc::PrivilegedJunkScope());
-    JSAutoCompartment ac(aCx, global);
+    JSAutoRealm ar(aCx, global);
 
     JS::RootedObject obj(aCx, JS_NewPlainObject(aCx));
     if (!obj) {
       aError.NoteJSContextException(aCx);
       return;
     }
 
     mInitialProcessData.setObject(*obj);
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -4125,17 +4125,17 @@ nsGlobalWindowInner::CallerInnerWindow()
 
   // When Jetpack runs content scripts inside a sandbox, it uses
   // sandboxPrototype to make them appear as though they're running in the
   // scope of the page. So when a content script invokes postMessage, it expects
   // the |source| of the received message to be the window set as the
   // sandboxPrototype. This used to work incidentally for unrelated reasons, but
   // now we need to do some special handling to support it.
   if (xpc::IsSandbox(scope)) {
-    JSAutoCompartment ac(cx, scope);
+    JSAutoRealm ar(cx, scope);
     JS::Rooted<JSObject*> scopeProto(cx);
     bool ok = JS_GetPrototype(cx, scope, &scopeProto);
     NS_ENSURE_TRUE(ok, nullptr);
     if (scopeProto && xpc::IsSandboxPrototypeProxy(scopeProto) &&
         (scopeProto = js::CheckedUnwrap(scopeProto, /* stopAtWindowProxy = */ false)))
     {
       global = xpc::NativeGlobal(scopeProto);
       NS_ENSURE_TRUE(global, nullptr);
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -788,17 +788,17 @@ nsChromeOuterWindowProxy::className(JSCo
 }
 
 const nsChromeOuterWindowProxy
 nsChromeOuterWindowProxy::singleton;
 
 static JSObject*
 NewOuterWindowProxy(JSContext *cx, JS::Handle<JSObject*> global, bool isChrome)
 {
-  JSAutoCompartment ac(cx, global);
+  JSAutoRealm ar(cx, global);
   MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(global) == global);
 
   js::WrapperOptions options;
   options.setClass(&OuterWindowProxyClass);
   options.setSingleton(true);
   JSObject *obj = js::Wrapper::New(cx, global,
                                    isChrome ? &nsChromeOuterWindowProxy::singleton
                                             : &nsOuterWindowProxy::singleton,
@@ -1530,17 +1530,17 @@ EnablePrivilege(JSContext* cx, unsigned 
 static const JSFunctionSpec EnablePrivilegeSpec[] = {
   JS_FN("enablePrivilege", EnablePrivilege, 1, 0),
   JS_FS_END
 };
 
 static bool
 InitializeLegacyNetscapeObject(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
 {
-  JSAutoCompartment ac(aCx, aGlobal);
+  JSAutoRealm ar(aCx, aGlobal);
 
   // Note: MathJax depends on window.netscape being exposed. See bug 791526.
   JS::Rooted<JSObject*> obj(aCx);
   obj = JS_DefineObject(aCx, aGlobal, "netscape", nullptr);
   NS_ENSURE_TRUE(obj, false);
 
   obj = JS_DefineObject(aCx, obj, "security", nullptr);
   NS_ENSURE_TRUE(obj, false);
@@ -1867,18 +1867,18 @@ nsGlobalWindowOuter::SetNewDocument(nsID
       SetWrapper(outerObject);
 
       MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(outerObject) == newInnerGlobal);
 
       // Inform the nsJSContext, which is the canonical holder of the outer.
       mContext->SetWindowProxy(outerObject);
     }
 
-    // Enter the new global's compartment.
-    JSAutoCompartment ac(cx, GetWrapperPreserveColor());
+    // Enter the new global's realm.
+    JSAutoRealm ar(cx, GetWrapperPreserveColor());
 
     {
       JS::Rooted<JSObject*> outer(cx, GetWrapperPreserveColor());
       js::SetWindowProxy(cx, newInnerGlobal, outer);
     }
 
     // Set scriptability based on the state of the docshell.
     bool allow = GetDocShell()->GetCanExecuteScripts();
@@ -1900,17 +1900,17 @@ nsGlobalWindowOuter::SetNewDocument(nsID
       // And same thing for the "self" property.
       if (!JS_GetProperty(cx, newInnerGlobal, "self", &unused)) {
         NS_ERROR("can't create the 'self' property");
         return NS_ERROR_FAILURE;
       }
     }
   }
 
-  JSAutoCompartment ac(cx, GetWrapperPreserveColor());
+  JSAutoRealm ar(cx, GetWrapperPreserveColor());
 
   if (!aState && !reUseInnerWindow) {
     // Loading a new page and creating a new inner window, *not*
     // restoring from session history.
 
     // Now that both the the inner and outer windows are initialized
     // let the script context do its magic to hook them together.
     MOZ_ASSERT(mContext->GetWindowProxy() == GetWrapperPreserveColor());
@@ -3803,17 +3803,17 @@ nsGlobalWindowOuter::DispatchResizeEvent
     return false;
   }
 
   // We don't init the AutoJSAPI with ourselves because we don't want it
   // reporting errors to our onerror handlers.
   AutoJSAPI jsapi;
   jsapi.Init();
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, GetWrapperPreserveColor());
+  JSAutoRealm ar(cx, GetWrapperPreserveColor());
 
   DOMWindowResizeEventDetail detail;
   detail.mWidth = aSize.width;
   detail.mHeight = aSize.height;
   JS::Rooted<JS::Value> detailValue(cx);
   if (!ToJSValue(cx, detail, &detailValue)) {
     return false;
   }
@@ -5599,17 +5599,17 @@ nsGlobalWindowOuter::CallerInnerWindow()
 
   // When Jetpack runs content scripts inside a sandbox, it uses
   // sandboxPrototype to make them appear as though they're running in the
   // scope of the page. So when a content script invokes postMessage, it expects
   // the |source| of the received message to be the window set as the
   // sandboxPrototype. This used to work incidentally for unrelated reasons, but
   // now we need to do some special handling to support it.
   if (xpc::IsSandbox(scope)) {
-    JSAutoCompartment ac(cx, scope);
+    JSAutoRealm ar(cx, scope);
     JS::Rooted<JSObject*> scopeProto(cx);
     bool ok = JS_GetPrototype(cx, scope, &scopeProto);
     NS_ENSURE_TRUE(ok, nullptr);
     if (scopeProto && xpc::IsSandboxPrototypeProxy(scopeProto) &&
         (scopeProto = js::CheckedUnwrap(scopeProto, /* stopAtWindowProxy = */ false)))
     {
       global = xpc::NativeGlobal(scopeProto);
       NS_ENSURE_TRUE(global, nullptr);
@@ -7147,17 +7147,17 @@ nsresult
 nsGlobalWindowOuter::SecurityCheckURL(const char *aURL)
 {
   nsCOMPtr<nsPIDOMWindowInner> sourceWindow = do_QueryInterface(GetEntryGlobal());
   if (!sourceWindow) {
     sourceWindow = GetCurrentInnerWindow();
   }
   AutoJSContext cx;
   nsGlobalWindowInner* sourceWin = nsGlobalWindowInner::Cast(sourceWindow);
-  JSAutoCompartment ac(cx, sourceWin->GetGlobalJSObject());
+  JSAutoRealm ar(cx, sourceWin->GetGlobalJSObject());
 
   // Resolve the baseURI, which could be relative to the calling window.
   //
   // Note the algorithm to get the base URI should match the one
   // used to actually kick off the load in nsWindowWatcher.cpp.
   nsCOMPtr<nsIDocument> doc = sourceWindow->GetDoc();
   nsIURI* baseURI = nullptr;
   auto encoding = UTF_8_ENCODING; // default to utf-8
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -1271,17 +1271,17 @@ CheckForOutdatedParent(nsINode* aParent,
     JS::Rooted<JSObject*> existingObj(RootingCx(), existingObjUnrooted);
 
     AutoJSContext cx;
     nsIGlobalObject* global = aParent->OwnerDoc()->GetScopeObject();
     MOZ_ASSERT(global);
 
     if (js::GetGlobalForObjectCrossCompartment(existingObj) !=
         global->GetGlobalJSObject()) {
-      JSAutoCompartment ac(cx, existingObj);
+      JSAutoRealm ar(cx, existingObj);
       ReparentWrapper(cx, existingObj, aError);
     }
   }
 }
 
 nsresult
 nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
                          bool aNotify, nsAttrAndChildArray& aChildArray)
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -788,17 +788,17 @@ nsJSContext::ConvertSupportsTojsvals(nsI
           // just wrap it.
 #ifdef DEBUG
           // but first, check its not another nsISupportsPrimitive, as
           // these are now deprecated for use with script contexts.
           nsCOMPtr<nsISupportsPrimitive> prim(do_QueryInterface(arg));
           NS_ASSERTION(prim == nullptr,
                        "Don't pass nsISupportsPrimitives - use nsIVariant!");
 #endif
-          JSAutoCompartment ac(cx, aScope);
+          JSAutoRealm ar(cx, aScope);
           rv = nsContentUtils::WrapNative(cx, arg, thisVal);
         }
       }
     }
   } else {
     nsCOMPtr<nsIVariant> variant = do_QueryInterface(aArgs);
     if (variant) {
       rv = xpc->VariantToJS(cx, aScope, variant, aArgsOut[0]);
@@ -979,17 +979,17 @@ nsJSContext::AddSupportsPrimitiveTojsval
       p->GetData(getter_AddRefs(data));
       p->GetDataIID(&iid);
       NS_ENSURE_TRUE(iid, NS_ERROR_UNEXPECTED);
 
       AutoFree iidGuard(iid); // Free iid upon destruction.
 
       JS::Rooted<JSObject*> scope(cx, GetWindowProxy());
       JS::Rooted<JS::Value> v(cx);
-      JSAutoCompartment ac(cx, scope);
+      JSAutoRealm ar(cx, scope);
       nsresult rv = nsContentUtils::WrapNative(cx, data, iid, &v);
       NS_ENSURE_SUCCESS(rv, rv);
 
       *aArgv = v;
 
       break;
     }
     case nsISupportsPrimitive::TYPE_ID :
@@ -1114,17 +1114,17 @@ static const JSFunctionSpec JProfFunctio
 #endif /* defined(MOZ_JPROF) */
 
 nsresult
 nsJSContext::InitClasses(JS::Handle<JSObject*> aGlobalObj)
 {
   AutoJSAPI jsapi;
   jsapi.Init();
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, aGlobalObj);
+  JSAutoRealm ar(cx, aGlobalObj);
 
   // Attempt to initialize profiling functions
   ::JS_DefineProfilingFunctions(cx, aGlobalObj);
 
 #ifdef MOZ_JPROF
   // Attempt to initialize JProf functions
   ::JS_DefineFunctions(cx, aGlobalObj, JProfFunctions);
 #endif
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -137,17 +137,17 @@ EvaluationExceptionToNSResult(JSContext*
 nsJSUtils::ExecutionContext::ExecutionContext(JSContext* aCx,
                                               JS::Handle<JSObject*> aGlobal)
   :
 #ifdef MOZ_GECKO_PROFILER
     mAutoProfilerLabel("nsJSUtils::ExecutionContext", /* dynamicStr */ nullptr,
                        __LINE__, js::ProfilingStackFrame::Category::JS),
 #endif
     mCx(aCx)
-  , mCompartment(aCx, aGlobal)
+  , mRealm(aCx, aGlobal)
   , mRetValue(aCx)
   , mScopeChain(aCx)
   , mRv(NS_OK)
   , mSkip(false)
   , mCoerceToString(false)
   , mEncodeBytecode(false)
 #ifdef DEBUG
   , mWantsReturnValue(false)
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -72,18 +72,18 @@ public:
   class MOZ_STACK_CLASS ExecutionContext {
 #ifdef MOZ_GECKO_PROFILER
     // Register stack annotations for the Gecko profiler.
     mozilla::AutoProfilerLabel mAutoProfilerLabel;
 #endif
 
     JSContext* mCx;
 
-    // Handles switching to our global's compartment.
-    JSAutoCompartment mCompartment;
+    // Handles switching to our global's realm.
+    JSAutoRealm mRealm;
 
     // Set to a valid handle if a return value is expected.
     JS::Rooted<JS::Value> mRetValue;
 
     // Scope chain in which the execution takes place.
     JS::AutoObjectVector mScopeChain;
 
     // returned value forwarded when we have to interupt the execution eagerly
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -579,17 +579,17 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
       elem->RecompileScriptEventListeners();
     }
 
     if (aReparentScope) {
       AutoJSContext cx;
       JS::Rooted<JSObject*> wrapper(cx);
       if ((wrapper = aNode->GetWrapper())) {
         MOZ_ASSERT(IsDOMObject(wrapper));
-        JSAutoCompartment ac(cx, wrapper);
+        JSAutoRealm ar(cx, wrapper);
         ReparentWrapper(cx, wrapper, aError);
         if (aError.Failed()) {
           if (wasRegistered) {
             aNode->OwnerDoc()->UnregisterActivityObserver(aNode->AsElement());
           }
           aNode->mNodeInfo.swap(newNodeInfo);
           if (elem) {
             elem->NodeInfoChanged(newDoc);
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -3558,22 +3558,22 @@ nsObjectLoadingContent::SetupProtoChain(
   }
 
   if (!nsContentUtils::IsSafeToRunScript()) {
     RefPtr<SetupProtoChainRunner> runner = new SetupProtoChainRunner(this);
     nsContentUtils::AddScriptRunner(runner);
     return;
   }
 
-  // We get called on random compartments here for some reason
-  // (perhaps because WrapObject can happen on a random compartment?)
-  // so make sure to enter the compartment of aObject.
+  // We get called on random realms here for some reason
+  // (perhaps because WrapObject can happen on a random realm?)
+  // so make sure to enter the realm of aObject.
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
 
-  JSAutoCompartment ac(aCx, aObject);
+  JSAutoRealm ar(aCx, aObject);
 
   RefPtr<nsNPAPIPluginInstance> pi;
   nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
   if (NS_FAILED(rv)) {
     return;
   }
 
   if (!pi) {
@@ -3668,20 +3668,19 @@ nsObjectLoadingContent::SetupProtoChain(
 // static
 nsresult
 nsObjectLoadingContent::GetPluginJSObject(JSContext *cx,
                                           JS::Handle<JSObject*> obj,
                                           nsNPAPIPluginInstance *plugin_inst,
                                           JS::MutableHandle<JSObject*> plugin_obj,
                                           JS::MutableHandle<JSObject*> plugin_proto)
 {
-  // NB: We need an AutoEnterCompartment because we can be called from
-  // nsPluginFrame when the plugin loads after the JS object for our content
-  // node has been created.
-  JSAutoCompartment ac(cx, obj);
+  // NB: We need a JSAutoRealm because we can be called from nsPluginFrame when
+  // the plugin loads after the JS object for our content node has been created.
+  JSAutoRealm ar(cx, obj);
 
   if (plugin_inst) {
     plugin_inst->GetJSObject(cx, plugin_obj.address());
     if (plugin_obj) {
       if (!::JS_GetPrototype(cx, plugin_obj, plugin_proto)) {
         return NS_ERROR_UNEXPECTED;
       }
     }
@@ -3702,17 +3701,17 @@ nsObjectLoadingContent::TeardownProtoCha
   // reporting errors to our window's onerror listeners.
   AutoJSAPI jsapi;
   jsapi.Init();
   JSContext* cx = jsapi.cx();
   JS::Rooted<JSObject*> obj(cx, thisContent->GetWrapper());
   MOZ_ASSERT(obj);
 
   JS::Rooted<JSObject*> proto(cx);
-  JSAutoCompartment ac(cx, obj);
+  JSAutoRealm ar(cx, obj);
 
   // Loop over the DOM element's JS object prototype chain and remove
   // all JS objects of the class sNPObjectJSWrapperClass
   DebugOnly<bool> removed = false;
   while (obj) {
     if (!::JS_GetPrototype(cx, obj, &proto)) {
       return;
     }
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1603,17 +1603,17 @@ static bool
 ResolvePrototypeOrConstructor(JSContext* cx, JS::Handle<JSObject*> wrapper,
                               JS::Handle<JSObject*> obj,
                               size_t protoAndIfaceCacheIndex, unsigned attrs,
                               JS::MutableHandle<JS::PropertyDescriptor> desc,
                               bool& cacheOnHolder)
 {
   JS::Rooted<JSObject*> global(cx, js::GetGlobalForObjectCrossCompartment(obj));
   {
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
     ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
     // This function is called when resolving the "constructor" and "prototype"
     // properties of Xrays for DOM prototypes and constructors respectively.
     // This means the relevant Xray exists, which means its _target_ exists.
     // And that means we managed to successfullly create the prototype or
     // constructor, respectively, and hence must have managed to create the
     // thing it's pointing to as well.  So our entry slot must exist.
     JSObject* protoOrIface =
@@ -2249,17 +2249,17 @@ ReparentWrapper(JSContext* aCx, JS::Hand
   JS::Rooted<JSObject*> oldParent(aCx,
                                   js::GetGlobalForObjectCrossCompartment(aObj));
   MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(oldParent) == oldParent);
 
   JS::Rooted<JSObject*> newParent(aCx,
                                   domClass->mGetAssociatedGlobal(aCx, aObj));
   MOZ_ASSERT(JS_IsGlobalObject(newParent));
 
-  JSAutoCompartment oldAc(aCx, oldParent);
+  JSAutoRealm oldAr(aCx, oldParent);
 
   JSCompartment* oldCompartment = js::GetObjectCompartment(oldParent);
   JSCompartment* newCompartment = js::GetObjectCompartment(newParent);
   if (oldCompartment == newCompartment) {
     MOZ_ASSERT(oldParent == newParent);
     return;
   }
 
@@ -2269,17 +2269,17 @@ ReparentWrapper(JSContext* aCx, JS::Hand
   }
 
   bool isProxy = js::IsProxy(aObj);
   JS::Rooted<JSObject*> expandoObject(aCx);
   if (isProxy) {
     expandoObject = DOMProxyHandler::GetAndClearExpandoObject(aObj);
   }
 
-  JSAutoCompartment newAc(aCx, newParent);
+  JSAutoRealm newAr(aCx, newParent);
 
   // First we clone the reflector. We get a copy of its properties and clone its
   // expando chain.
 
   JS::Handle<JSObject*> proto = (domClass->mGetProto)(aCx);
   if (!proto) {
     aError.StealExceptionFromJSContext(aCx);
     return;
@@ -3505,20 +3505,20 @@ GetMaplikeSetlikeBackingObject(JSContext
   reflector = IsDOMObject(aObj) ? aObj : js::UncheckedUnwrap(aObj,
                                                              /* stopAtWindowProxy = */ false);
 
   // Retrieve the backing object from the reserved slot on the maplike/setlike
   // object. If it doesn't exist yet, create it.
   JS::Rooted<JS::Value> slotValue(aCx);
   slotValue = js::GetReservedSlot(reflector, aSlotIndex);
   if (slotValue.isUndefined()) {
-    // Since backing object access can happen in non-originating compartments,
-    // make sure to create the backing object in reflector compartment.
+    // Since backing object access can happen in non-originating realms,
+    // make sure to create the backing object in reflector realm.
     {
-      JSAutoCompartment ac(aCx, reflector);
+      JSAutoRealm ar(aCx, reflector);
       JS::Rooted<JSObject*> newBackingObj(aCx);
       newBackingObj.set(Method(aCx));
       if (NS_WARN_IF(!newBackingObj)) {
         return false;
       }
       js::SetReservedSlot(reflector, aSlotIndex, JS::ObjectValue(*newBackingObj));
     }
     slotValue = js::GetReservedSlot(reflector, aSlotIndex);
@@ -3731,17 +3731,17 @@ HTMLConstructor(JSContext* aCx, unsigned
   // Enter the compartment of our underlying newTarget object, so we end
   // up comparing to the constructor object for our interface from that global.
   // XXXbz This is not what the spec says to do, and it's not super-clear to me
   // at this point why we're doing it.  Why not just compare |newTarget| and
   // |callee| if the intent is just to prevent registration of HTML interface
   // objects as constructors?  Of course it's not clear that the spec check
   // makes sense to start with: https://github.com/whatwg/html/issues/3575
   {
-    JSAutoCompartment ac(aCx, newTarget);
+    JSAutoRealm ar(aCx, newTarget);
     JS::Handle<JSObject*> constructor =
       GetPerInterfaceObjectHandle(aCx, aConstructorId, aCreator,
                                   true);
     if (!constructor) {
       return false;
     }
     if (newTarget == constructor) {
       return ThrowErrorMessage(aCx, MSG_ILLEGAL_CONSTRUCTOR);
@@ -3764,19 +3764,19 @@ HTMLConstructor(JSContext* aCx, unsigned
     ns = kNameSpaceID_XHTML;
   }
 
   int32_t tag = eHTMLTag_userdefined;
   if (!definition->IsCustomBuiltIn()) {
     // Step 4.
     // If the definition is for an autonomous custom element, the active
     // function should be HTMLElement or XULElement.  We want to get the actual
-    // functions to compare to from our global's compartment, not the caller
-    // compartment.
-    JSAutoCompartment ac(aCx, global.Get());
+    // functions to compare to from our global's realm, not the caller
+    // realm.
+    JSAutoRealm ar(aCx, global.Get());
 
     JS::Rooted<JSObject*> constructor(aCx);
     if (ns == kNameSpaceID_XUL) {
       constructor = XULElementBinding::GetConstructorObject(aCx);
     } else {
       constructor = HTMLElementBinding::GetConstructorObject(aCx);
     }
 
@@ -3806,19 +3806,19 @@ HTMLConstructor(JSContext* aCx, unsigned
 
     // If the definition is for a customized built-in element, the active
     // function should be the localname's element interface.
     constructorGetterCallback cb = sConstructorGetterCallback[tag];
     if (!cb) {
       return ThrowErrorMessage(aCx, MSG_ILLEGAL_CONSTRUCTOR);
     }
 
-    // We want to get the constructor from our global's compartment, not the
-    // caller compartment.
-    JSAutoCompartment ac(aCx, global.Get());
+    // We want to get the constructor from our global's realm, not the
+    // caller realm.
+    JSAutoRealm ar(aCx, global.Get());
     JS::Rooted<JSObject*> constructor(aCx, cb(aCx));
     if (!constructor) {
       return false;
     }
 
     if (constructor != js::CheckedUnwrap(callee)) {
       return ThrowErrorMessage(aCx, MSG_ILLEGAL_CONSTRUCTOR);
     }
@@ -3828,49 +3828,49 @@ HTMLConstructor(JSContext* aCx, unsigned
   JS::Rooted<JSObject*> desiredProto(aCx);
   if (!GetDesiredProto(aCx, args, &desiredProto)) {
     return false;
   }
 
   // Step 7.
   if (!desiredProto) {
     // This fallback behavior is designed to match analogous behavior for the
-    // JavaScript built-ins. So we enter the compartment of our underlying
-    // newTarget object and fall back to the prototype object from that global.
+    // JavaScript built-ins. So we enter the realm of our underlying newTarget
+    // object and fall back to the prototype object from that global.
     // XXX The spec says to use GetFunctionRealm(), which is not actually
     // the same thing as what we have here (e.g. in the case of scripted callable proxies
-    // whose target is not same-compartment with the proxy, or bound functions, etc).
+    // whose target is not same-realm with the proxy, or bound functions, etc).
     // https://bugzilla.mozilla.org/show_bug.cgi?id=1317658
     {
-      JSAutoCompartment ac(aCx, newTarget);
+      JSAutoRealm ar(aCx, newTarget);
       desiredProto = GetPerInterfaceObjectHandle(aCx, aProtoId, aCreator, true);
       if (!desiredProto) {
           return false;
       }
     }
 
-    // desiredProto is in the compartment of the underlying newTarget object.
-    // Wrap it into the context compartment.
+    // desiredProto is in the realm of the underlying newTarget object.
+    // Wrap it into the context realm.
     if (!JS_WrapObject(aCx, &desiredProto)) {
       return false;
     }
   }
 
   // We need to do some work to actually return an Element, so we do step 8 on
   // one branch and steps 9-12 on another branch, then common up the "return
   // element" work.
   RefPtr<Element> element;
   nsTArray<RefPtr<Element>>& constructionStack =
     definition->mConstructionStack;
   if (constructionStack.IsEmpty()) {
     // Step 8.
     // Now we go to construct an element.  We want to do this in global's
-    // compartment, not caller compartment (the normal constructor behavior),
+    // realm, not caller realm (the normal constructor behavior),
     // just in case those elements create JS things.
-    JSAutoCompartment ac(aCx, global.Get());
+    JSAutoRealm ar(aCx, global.Get());
 
     RefPtr<NodeInfo> nodeInfo =
       doc->NodeInfoManager()->GetNodeInfo(definition->mLocalName,
                                           nullptr,
                                           ns,
                                           nsINode::ELEMENT_NODE);
     MOZ_ASSERT(nodeInfo);
 
@@ -3902,33 +3902,33 @@ HTMLConstructor(JSContext* aCx, unsigned
 
     // Step 11.
     // Do prototype swizzling for upgrading a custom element here, for cases
     // when we have a reflector already.  If we don't have one yet, we will
     // create it with the right proto (by calling DoGetOrCreateDOMReflector with
     // that proto).
     JS::Rooted<JSObject*> reflector(aCx, element->GetWrapper());
     if (reflector) {
-      // reflector might be in different compartment.
-      JSAutoCompartment ac(aCx, reflector);
+      // reflector might be in different realm.
+      JSAutoRealm ar(aCx, reflector);
       JS::Rooted<JSObject*> givenProto(aCx, desiredProto);
       if (!JS_WrapObject(aCx, &givenProto) ||
           !JS_SetPrototype(aCx, reflector, givenProto)) {
         return false;
       }
     }
 
     // Step 12.
     constructionStack.LastElement() = ALREADY_CONSTRUCTED_MARKER;
   }
 
   // Tail end of step 8 and step 13: returning the element.  We want to do this
-  // part in the global's compartment, though in practice it won't matter much
-  // because Element always knows which compartment it should be created in.
-  JSAutoCompartment ac(aCx, global.Get());
+  // part in the global's realm, though in practice it won't matter much
+  // because Element always knows which realm it should be created in.
+  JSAutoRealm ar(aCx, global.Get());
   if (!js::IsObjectInContextCompartment(desiredProto, aCx) &&
       !JS_WrapObject(aCx, &desiredProto)) {
     return false;
   }
 
   return GetOrCreateDOMReflector(aCx, element, args.rval(), desiredProto);
 }
 } // namespace binding_detail
@@ -3940,21 +3940,21 @@ AssertReflectorHasGivenProto(JSContext* 
                              JS::Handle<JSObject*> aGivenProto)
 {
   if (!aGivenProto) {
     // Nothing to assert here
     return;
   }
 
   JS::Rooted<JSObject*> reflector(aCx, aReflector);
-  JSAutoCompartment ac(aCx, reflector);
+  JSAutoRealm ar(aCx, reflector);
   JS::Rooted<JSObject*> reflectorProto(aCx);
   bool ok = JS_GetPrototype(aCx, reflector, &reflectorProto);
   MOZ_ASSERT(ok);
-  // aGivenProto may not be in the right compartment here, so we
+  // aGivenProto may not be in the right realm here, so we
   // have to wrap it to compare.
   JS::Rooted<JSObject*> givenProto(aCx, aGivenProto);
   ok = JS_WrapObject(aCx, &givenProto);
   MOZ_ASSERT(ok);
   MOZ_ASSERT(givenProto == reflectorProto,
              "How are we supposed to change the proto now?");
 }
 } // namespace binding_detail
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1123,17 +1123,17 @@ DoGetOrCreateDOMReflector(JSContext* cx,
   bool sameCompartment =
     js::GetObjectCompartment(obj) == js::GetContextCompartment(cx);
   if (sameCompartment && couldBeDOMBinding) {
     return TypeNeedsOuterization<T>::value ? TryToOuterize(rval) : true;
   }
 
   if (wrapBehavior == eDontWrapIntoContextCompartment) {
     if (TypeNeedsOuterization<T>::value) {
-      JSAutoCompartment ac(cx, obj);
+      JSAutoRealm ar(cx, obj);
       return TryToOuterize(rval);
     }
 
     return true;
   }
 
   return JS_WrapValue(cx, rval);
 }
@@ -1183,32 +1183,32 @@ inline bool
 WrapNewBindingNonWrapperCachedObject(JSContext* cx,
                                      JS::Handle<JSObject*> scopeArg,
                                      T* value,
                                      JS::MutableHandle<JS::Value> rval,
                                      JS::Handle<JSObject*> givenProto = nullptr)
 {
   static_assert(IsRefcounted<T>::value, "Don't pass owned classes in here.");
   MOZ_ASSERT(value);
-  // We try to wrap in the compartment of the underlying object of "scope"
+  // We try to wrap in the realm of the underlying object of "scope"
   JS::Rooted<JSObject*> obj(cx);
   {
-    // scope for the JSAutoCompartment so that we restore the compartment
+    // scope for the JSAutoRealm so that we restore the realm
     // before we call JS_WrapValue.
-    Maybe<JSAutoCompartment> ac;
+    Maybe<JSAutoRealm> ar;
     // Maybe<Handle> doesn't so much work, and in any case, adding
     // more Maybe (one for a Rooted and one for a Handle) adds more
     // code (and branches!) than just adding a single rooted.
     JS::Rooted<JSObject*> scope(cx, scopeArg);
     JS::Rooted<JSObject*> proto(cx, givenProto);
     if (js::IsWrapper(scope)) {
       scope = js::CheckedUnwrap(scope, /* stopAtWindowProxy = */ false);
       if (!scope)
         return false;
-      ac.emplace(cx, scope);
+      ar.emplace(cx, scope);
       if (!JS_WrapObject(cx, &proto)) {
         return false;
       }
     }
 
     MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
     if (!value->WrapObject(cx, proto, &obj)) {
       return false;
@@ -1234,32 +1234,32 @@ WrapNewBindingNonWrapperCachedObject(JSC
                                      JS::Handle<JSObject*> givenProto = nullptr)
 {
   static_assert(!IsRefcounted<T>::value, "Only pass owned classes in here.");
   // We do a runtime check on value, because otherwise we might in
   // fact end up wrapping a null and invoking methods on it later.
   if (!value) {
     MOZ_CRASH("Don't try to wrap null objects");
   }
-  // We try to wrap in the compartment of the underlying object of "scope"
+  // We try to wrap in the realm of the underlying object of "scope"
   JS::Rooted<JSObject*> obj(cx);
   {
-    // scope for the JSAutoCompartment so that we restore the compartment
+    // scope for the JSAutoRealm so that we restore the realm
     // before we call JS_WrapValue.
-    Maybe<JSAutoCompartment> ac;
+    Maybe<JSAutoRealm> ar;
     // Maybe<Handle> doesn't so much work, and in any case, adding
     // more Maybe (one for a Rooted and one for a Handle) adds more
     // code (and branches!) than just adding a single rooted.
     JS::Rooted<JSObject*> scope(cx, scopeArg);
     JS::Rooted<JSObject*> proto(cx, givenProto);
     if (js::IsWrapper(scope)) {
       scope = js::CheckedUnwrap(scope, /* stopAtWindowProxy = */ false);
       if (!scope)
         return false;
-      ac.emplace(cx, scope);
+      ar.emplace(cx, scope);
       if (!JS_WrapObject(cx, &proto)) {
         return false;
       }
     }
 
     MOZ_ASSERT(js::IsObjectInContextCompartment(scope, cx));
     if (!value->WrapObject(cx, proto, &obj)) {
       return false;
@@ -2505,17 +2505,17 @@ XrayOwnPropertyKeys(JSContext* cx, JS::H
  *     interface or interface prototype object.
  */
 inline bool
 XrayGetNativeProto(JSContext* cx, JS::Handle<JSObject*> obj,
                    JS::MutableHandle<JSObject*> protop)
 {
   JS::Rooted<JSObject*> global(cx, js::GetGlobalForObjectCrossCompartment(obj));
   {
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
     const DOMJSClass* domClass = GetDOMClass(obj);
     if (domClass) {
       ProtoHandleGetter protoGetter = domClass->mGetProto;
       if (protoGetter) {
         protop.set(protoGetter(cx));
       } else {
         protop.set(JS::GetRealmObjectPrototype(cx));
       }
@@ -3146,17 +3146,17 @@ CreateGlobal(JSContext* aCx, T* aNative,
 
   aGlobal.set(JS_NewGlobalObject(aCx, aClass, aPrincipal,
                                  JS::DontFireOnNewGlobalHook, aOptions));
   if (!aGlobal) {
     NS_WARNING("Failed to create global");
     return false;
   }
 
-  JSAutoCompartment ac(aCx, aGlobal);
+  JSAutoRealm ar(aCx, aGlobal);
 
   {
     js::SetReservedSlot(aGlobal, DOM_OBJECT_SLOT, JS::PrivateValue(aNative));
     NS_ADDREF(aNative);
 
     aCache->SetWrapper(aGlobal);
 
     dom::AllocateProtoAndIfaceCache(aGlobal,
@@ -3335,17 +3335,17 @@ WrappedJSToDictionary(JSContext* aCx, ns
     return false;
   }
 
   JS::Rooted<JSObject*> obj(aCx, wrappedObj->GetJSObject());
   if (!obj) {
     return false;
   }
 
-  JSAutoCompartment ac(aCx, obj);
+  JSAutoRealm ar(aCx, obj);
   JS::Rooted<JS::Value> v(aCx, JS::ObjectValue(*obj));
   return aDictionary.Init(aCx, v);
 }
 
 template<class T>
 inline bool
 WrappedJSToDictionary(nsISupports* aObject, T& aDictionary)
 {
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -241,22 +241,22 @@ CallbackObject::CallSetup::CallSetup(Cal
   // JSContext. (Rooted<> does not care about requests or compartments.)
   mRootedCallable.emplace(cx, aCallback->CallbackOrNull());
 
   mAsyncStack.emplace(cx, aCallback->GetCreationStack());
   if (*mAsyncStack) {
     mAsyncStackSetter.emplace(cx, *mAsyncStack, aExecutionReason);
   }
 
-  // Enter the compartment of our callback, so we can actually work with it.
+  // Enter the realm of our callback, so we can actually work with it.
   //
   // Note that if the callback is a wrapper, this will not be the same
-  // compartment that we ended up in with mAutoEntryScript above, because the
+  // realm that we ended up in with mAutoEntryScript above, because the
   // entry point is based off of the unwrapped callback (realCallback).
-  mAc.emplace(cx, *mRootedCallable);
+  mAr.emplace(cx, *mRootedCallable);
 
   // And now we're ready to go.
   mCx = cx;
 }
 
 bool
 CallbackObject::CallSetup::ShouldRethrowException(JS::Handle<JS::Value> aException)
 {
@@ -297,22 +297,22 @@ CallbackObject::CallSetup::ShouldRethrow
 
   JS::Rooted<JSObject*> obj(mCx, &aException.toObject());
   obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
   return js::GetObjectCompartment(obj) == mCompartment;
 }
 
 CallbackObject::CallSetup::~CallSetup()
 {
-  // To get our nesting right we have to destroy our JSAutoCompartment first.
+  // To get our nesting right we have to destroy our JSAutoRealm first.
   // In particular, we want to do this before we try reporting any exceptions,
-  // so we end up reporting them while in the compartment of our entry point,
+  // so we end up reporting them while in the realm of our entry point,
   // not whatever cross-compartment wrappper mCallback might be.
-  // Be careful: the JSAutoCompartment might not have been constructed at all!
-  mAc.reset();
+  // Be careful: the JSAutoRealm might not have been constructed at all!
+  mAr.reset();
 
   // Now, if we have a JSContext, report any pending errors on it, unless we
   // were told to re-throw them.
   if (mCx) {
     bool needToDealWithException = mAutoEntryScript->HasException();
     if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
         mExceptionHandling == eRethrowExceptions) {
       mErrorResult.MightThrowJSException();
@@ -327,17 +327,17 @@ CallbackObject::CallSetup::~CallSetup()
         }
       }
     }
 
     if (needToDealWithException) {
       // Either we're supposed to report our exceptions, or we're supposed to
       // re-throw them but we failed to get the exception value.  Either way,
       // we'll just report the pending exception, if any, once ~mAutoEntryScript
-      // runs.  Note that we've already run ~mAc, effectively, so we don't have
+      // runs.  Note that we've already run ~mAr, effectively, so we don't have
       // to worry about ordering here.
       if (mErrorResult.IsJSContextException()) {
         // XXXkhuey bug 1117269.  When this is fixed, please consider fixing
         // ThrowExceptionValueIfSafe over in Exceptions.cpp in the same way.
 
         // IsJSContextException shouldn't be true anymore because we will report
         // the exception on the JSContext ... so throw something else.
         mErrorResult.ThrowWithCustomCleanup(NS_ERROR_UNEXPECTED);
@@ -371,17 +371,17 @@ CallbackObjectHolderBase::ToXPCOMCallbac
   jsapi.Init();
   JSContext* cx = jsapi.cx();
 
   JS::Rooted<JSObject*> callback(cx, aCallback->CallbackOrNull());
   if (!callback) {
     return nullptr;
   }
 
-  JSAutoCompartment ac(cx, callback);
+  JSAutoRealm ar(cx, callback);
   RefPtr<nsXPCWrappedJS> wrappedJS;
   nsresult rv =
     nsXPCWrappedJS::GetNewOrUsed(callback, aIID, getter_AddRefs(wrappedJS));
   if (NS_FAILED(rv) || !wrappedJS) {
     return nullptr;
   }
 
   nsCOMPtr<nsISupports> retval;
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -332,21 +332,21 @@ protected:
     Maybe<AutoIncumbentScript> mAutoIncumbentScript;
 
     Maybe<JS::Rooted<JSObject*> > mRootedCallable;
 
     // Members which are used to set the async stack.
     Maybe<JS::Rooted<JSObject*>> mAsyncStack;
     Maybe<JS::AutoSetAsyncStackForNewCalls> mAsyncStackSetter;
 
-    // Can't construct a JSAutoCompartment without a JSContext either.  Also,
-    // Put mAc after mAutoEntryScript so that we exit the compartment before
-    // we pop the JSContext. Though in practice we'll often manually order
-    // those two things.
-    Maybe<JSAutoCompartment> mAc;
+    // Can't construct a JSAutoRealm without a JSContext either.  Also,
+    // Put mAr after mAutoEntryScript so that we exit the realm before we
+    // pop the script settings stack. Though in practice we'll often manually
+    // order those two things.
+    Maybe<JSAutoRealm> mAr;
 
     // An ErrorResult to possibly re-throw exceptions on and whether
     // we should re-throw them.
     ErrorResult& mErrorResult;
     const ExceptionHandling mExceptionHandling;
     const bool mIsMainThread;
   };
 };
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3740,17 +3740,17 @@ class CGWrapWithCacheMethod(CGAbstractMe
             aReflector.set(aCache->GetWrapper());
             if (aReflector) {
             #ifdef DEBUG
               AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
             #endif // DEBUG
               return true;
             }
 
-            JSAutoCompartment ac(aCx, global);
+            JSAutoRealm ar(aCx, global);
             $*{declareProto}
 
             $*{createObject}
 
             aCache->SetWrapper(aReflector);
             $*{unforgeable}
             $*{slots}
             $*{setImmutablePrototype}
@@ -3901,19 +3901,19 @@ class CGWrapGlobalMethod(CGAbstractMetho
                                              sClass.ToJSClass(),
                                              aOptions,
                                              aPrincipal,
                                              aInitStandardClasses,
                                              aReflector)) {
               $*{failureCode}
             }
 
-            // aReflector is a new global, so has a new compartment.  Enter it
+            // aReflector is a new global, so has a new realm.  Enter it
             // before doing anything with it.
-            JSAutoCompartment ac(aCx, aReflector);
+            JSAutoRealm ar(aCx, aReflector);
 
             if (!DefineProperties(aCx, aReflector, ${properties}, ${chromeProperties})) {
               $*{failureCode}
             }
             $*{unforgeable}
 
             $*{slots}
 
@@ -3988,17 +3988,17 @@ class CGClearCachedValueMethod(CGAbstrac
             noopRetval = " true"
             saveMember = (
                 "JS::Rooted<JS::Value> oldValue(aCx, js::GetReservedSlot(obj, %s));\n" %
                 slotIndex)
             regetMember = fill(
                 """
                 JS::Rooted<JS::Value> temp(aCx);
                 JSJitGetterCallArgs args(&temp);
-                JSAutoCompartment ac(aCx, obj);
+                JSAutoRealm ar(aCx, obj);
                 if (!get_${name}(aCx, obj, aObject, args)) {
                   js::SetReservedSlot(obj, ${slotIndex}, oldValue);
                   return false;
                 }
                 return true;
                 """,
                 name=self.member.identifier.name,
                 slotIndex=slotIndex)
@@ -5383,22 +5383,22 @@ def getJSToNativeConversionInfo(type, de
         else:
             getPromiseGlobal = dedent(
                 """
                 globalObj = JS::CurrentGlobalOrNull(cx);
                 """)
 
         templateBody = fill(
             """
-            { // Scope for our GlobalObject, FastErrorResult, JSAutoCompartment,
+            { // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
               // etc.
 
               JS::Rooted<JSObject*> globalObj(cx);
               $*{getPromiseGlobal}
-              JSAutoCompartment ac(cx, globalObj);
+              JSAutoRealm ar(cx, globalObj);
               GlobalObject promiseGlobal(cx, globalObj);
               if (promiseGlobal.Failed()) {
                 $*{exceptionCode}
               }
 
               JS::Rooted<JS::Value> valueToResolve(cx, $${val});
               if (!JS_WrapValue(cx, &valueToResolve)) {
                 $*{exceptionCode}
@@ -7631,18 +7631,18 @@ class CGPerSignatureCall(CGThing):
                 # object's compartment and then wrap up all of our arguments into
                 # that compartment as needed.  This is all happening after we've
                 # already done the conversions from JS values to WebIDL (C++)
                 # values, so we only need to worry about cases where there are 'any'
                 # or 'object' types, or other things that we represent as actual
                 # JSAPI types, present.  Effectively, we're emulating a
                 # CrossCompartmentWrapper, but working with the C++ types, not the
                 # original list of JS::Values.
-                cgThings.append(CGGeneric("Maybe<JSAutoCompartment> ac;\n"))
-                xraySteps.append(CGGeneric("ac.emplace(cx, obj);\n"))
+                cgThings.append(CGGeneric("Maybe<JSAutoRealm> ar;\n"))
+                xraySteps.append(CGGeneric("ar.emplace(cx, obj);\n"))
                 xraySteps.append(CGGeneric(dedent(
                     """
                     if (!JS_WrapObject(cx, &desiredProto)) {
                       return false;
                     }
                     """)))
                 xraySteps.extend(
                     wrapArgIntoCurrentCompartment(arg, argname, isMember=False)
@@ -7842,27 +7842,27 @@ class CGPerSignatureCall(CGThing):
                 conversionScope = "isXray ? obj : slotStorage"
             else:
                 conversionScope = "slotStorage"
 
             wrapCode = fill(
                 """
                 {
                   JS::Rooted<JSObject*> conversionScope(cx, ${conversionScope});
-                  JSAutoCompartment ac(cx, conversionScope);
+                  JSAutoRealm ar(cx, conversionScope);
                   do { // block we break out of when done wrapping
                     $*{wrapCode}
                   } while (false);
                   $*{postConversionSteps}
                 }
-                { // And now store things in the compartment of our slotStorage.
-                  JSAutoCompartment ac(cx, slotStorage);
+                { // And now store things in the realm of our slotStorage.
+                  JSAutoRealm ar(cx, slotStorage);
                   $*{slotStorageSteps}
                 }
-                // And now make sure args.rval() is in the caller compartment
+                // And now make sure args.rval() is in the caller realm.
                 return ${maybeWrap}(cx, args.rval());
                 """,
                 conversionScope=conversionScope,
                 wrapCode=wrapCode,
                 postConversionSteps=postConversionSteps,
                 slotStorageSteps=slotStorageSteps,
                 maybeWrap=getMaybeWrapValueFuncForType(self.idlNode.type))
         return wrapCode
@@ -10855,17 +10855,17 @@ class CGResolveOwnPropertyViaResolve(CGA
         return CGGeneric(dedent("""
             {
               // Since we're dealing with an Xray, do the resolve on the
               // underlying object first.  That gives it a chance to
               // define properties on the actual object as needed, and
               // then use the fact that it created the objects as a flag
               // to avoid re-resolving the properties if someone deletes
               // them.
-              JSAutoCompartment ac(cx, obj);
+              JSAutoRealm ar(cx, obj);
               JS_MarkCrossZoneId(cx, id);
               JS::Rooted<JS::PropertyDescriptor> objDesc(cx);
               if (!self->DoResolve(cx, obj, id, &objDesc)) {
                 return false;
               }
               // If desc.value() is undefined, then the DoResolve call
               // has already defined the property on the object.  Don't
               // try to also define it.
@@ -11550,17 +11550,17 @@ class CGDeleteNamedProperty(CGAbstractSt
                                         "bool", args)
 
     def definition_body(self):
         return fill(
             """
             MOZ_ASSERT(xpc::WrapperFactory::IsXrayWrapper(xray));
             MOZ_ASSERT(js::IsProxy(proxy));
             MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy));
-            JSAutoCompartment ac(cx, proxy);
+            JSAutoRealm ar(cx, proxy);
             bool deleteSucceeded = false;
             bool found = false;
             $*{namedBody}
             if (!found || deleteSucceeded) {
               return opresult.succeed();
             }
             return opresult.failCantDelete();
             """,
@@ -12749,17 +12749,17 @@ class CGDictionary(CGThing):
                 AutoJSAPI jsapi;
                 jsapi.Init();
                 JSContext *cx = jsapi.cx();
                 // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here
                 // because we'll only be creating objects, in ways that have no
                 // side-effects, followed by a call to JS::ToJSONMaybeSafely,
                 // which likewise guarantees no side-effects for the sorts of
                 // things we will pass it.
-                JSAutoCompartment ac(cx, UnprivilegedJunkScopeOrWorkerGlobal());
+                JSAutoRealm ar(cx, UnprivilegedJunkScopeOrWorkerGlobal());
                 JS::Rooted<JS::Value> val(cx);
                 if (!ToObjectInternal(cx, &val)) {
                   return false;
                 }
                 JS::Rooted<JSObject*> obj(cx, &val.toObject());
                 return StringifyToJSON(cx, obj, aJSON);
             """), const=True)
 
@@ -15301,17 +15301,17 @@ class CGJSImplClass(CGBindingImplClass):
         return fill(
             """
             JS::Rooted<JSObject*> obj(aCx, ${name}Binding::Wrap(aCx, this, aGivenProto));
             if (!obj) {
               return nullptr;
             }
 
             // Now define it on our chrome object
-            JSAutoCompartment ac(aCx, mImpl->CallbackOrNull());
+            JSAutoRealm ar(aCx, mImpl->CallbackOrNull());
             if (!JS_WrapObject(aCx, &obj)) {
               return nullptr;
             }
             if (!JS_DefineProperty(aCx, mImpl->CallbackOrNull(), "__DOM_IMPL__", obj, 0)) {
               return nullptr;
             }
             return obj;
             """,
@@ -16679,27 +16679,27 @@ class CGMaplikeOrSetlikeHelperFunctionGe
             """
             MOZ_ASSERT(self);
             AutoJSAPI jsapi;
             jsapi.Init();
             JSContext* cx = jsapi.cx();
             // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
             // all we want is to wrap into _some_ scope and then unwrap to find
             // the reflector, and wrapping has no side-effects.
-            JSAutoCompartment tempCompartment(cx, UnprivilegedJunkScopeOrWorkerGlobal());
+            JSAutoRealm tempRealm(cx, UnprivilegedJunkScopeOrWorkerGlobal());
             JS::Rooted<JS::Value> v(cx);
             if(!ToJSValue(cx, self, &v)) {
               aRv.Throw(NS_ERROR_UNEXPECTED);
               return%s;
             }
             // This is a reflector, but due to trying to name things
             // similarly across method generators, it's called obj here.
             JS::Rooted<JSObject*> obj(cx);
             obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
-            JSAutoCompartment reflectorCompartment(cx, obj);
+            JSAutoRealm reflectorRealm(cx, obj);
             """ % self.getDefaultRetval())
 
     def getArgs(self, returnType, argList):
         # We don't need the context or the value. We'll generate those instead.
         args = CGNativeMember.getArgs(self, returnType, argList)
         # Prepend a pointer to the binding object onto the arguments
         return [Argument(self.descriptorProvider.nativeType + "*", "self")] + args
 
--- a/dom/bindings/SimpleGlobalObject.cpp
+++ b/dom/bindings/SimpleGlobalObject.cpp
@@ -129,17 +129,17 @@ SimpleGlobalObject::Create(GlobalType gl
                                   JS::DontFireOnNewGlobalHook, options);
     }
 
     if (!global) {
       jsapi.ClearException();
       return nullptr;
     }
 
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     // It's important to create the nsIGlobalObject for our new global before we
     // start trying to wrap things like the prototype into its compartment,
     // because the wrap operation relies on the global having its
     // nsIGlobalObject already.
     RefPtr<SimpleGlobalObject> globalObject =
       new SimpleGlobalObject(global, globalType);
 
--- a/dom/bindings/StructuredClone.cpp
+++ b/dom/bindings/StructuredClone.cpp
@@ -42,17 +42,17 @@ ReadStructuredCloneImageData(JSContext* 
 bool
 WriteStructuredCloneImageData(JSContext* aCx, JSStructuredCloneWriter* aWriter,
                               ImageData* aImageData)
 {
   uint32_t width = aImageData->Width();
   uint32_t height = aImageData->Height();
   JS::Rooted<JSObject*> dataArray(aCx, aImageData->GetDataObject());
 
-  JSAutoCompartment ac(aCx, dataArray);
+  JSAutoRealm ar(aCx, dataArray);
   JS::Rooted<JS::Value> arrayValue(aCx, JS::ObjectValue(*dataArray));
   return JS_WriteUint32Pair(aWriter, SCTAG_DOM_IMAGEDATA, 0) &&
          JS_WriteUint32Pair(aWriter, width, height) &&
          JS_WriteTypedArray(aWriter, arrayValue);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/bindings/TypedArray.h
+++ b/dom/bindings/TypedArray.h
@@ -167,19 +167,19 @@ public:
     : Base(Move(aOther))
   {
   }
 
   static inline JSObject*
   Create(JSContext* cx, nsWrapperCache* creator, uint32_t length,
          const T* data = nullptr) {
     JS::Rooted<JSObject*> creatorWrapper(cx);
-    Maybe<JSAutoCompartment> ac;
+    Maybe<JSAutoRealm> ar;
     if (creator && (creatorWrapper = creator->GetWrapperPreserveColor())) {
-      ac.emplace(cx, creatorWrapper);
+      ar.emplace(cx, creatorWrapper);
     }
 
     return CreateCommon(cx, length, data);
   }
 
   static inline JSObject*
   Create(JSContext* cx, uint32_t length, const T* data = nullptr) {
     return CreateCommon(cx, length, data);
--- a/dom/bindings/WebIDLGlobalNameHash.cpp
+++ b/dom/bindings/WebIDLGlobalNameHash.cpp
@@ -303,17 +303,17 @@ WebIDLGlobalNameHash::DefineIfEnabled(JS
   //   slots are set up. In the Xray case, this means unwrapping and doing
   //   a non-Xray resolve before doing the Xray resolve.
   //
   // This all could use some grand refactoring, but for now we just limp
   // along.
   if (xpc::WrapperFactory::IsXrayWrapper(aObj)) {
     JS::Rooted<JSObject*> constructor(aCx);
     {
-      JSAutoCompartment ac(aCx, global);
+      JSAutoRealm ar(aCx, global);
       constructor = FindNamedConstructorForXray(aCx, aId, entry);
     }
     if (NS_WARN_IF(!constructor)) {
       return Throw(aCx, NS_ERROR_FAILURE);
     }
     if (!JS_WrapObject(aCx, &constructor)) {
       return Throw(aCx, NS_ERROR_FAILURE);
     }
--- a/dom/browser-element/BrowserElementParent.cpp
+++ b/dom/browser-element/BrowserElementParent.cpp
@@ -141,17 +141,17 @@ BrowserElementParent::DispatchOpenWindow
   JS::Rooted<JS::Value> val(cx);
 
   nsIGlobalObject* sgo = aPopupFrameElement->OwnerDoc()->GetScopeObject();
   if (!sgo) {
     return BrowserElementParent::OPEN_WINDOW_IGNORED;
   }
 
   JS::Rooted<JSObject*> global(cx, sgo->GetGlobalJSObject());
-  JSAutoCompartment ac(cx, global);
+  JSAutoRealm ar(cx, global);
   if (!ToJSValue(cx, detail, &val)) {
     MOZ_CRASH("Failed to convert dictionary to JS::Value due to OOM.");
     return BrowserElementParent::OPEN_WINDOW_IGNORED;
   }
 
   nsEventStatus status = nsEventStatus_eIgnore;
   bool dispatchSucceeded =
     DispatchCustomDOMEvent(aOpenerFrameElement,
--- a/dom/canvas/WebGLContextUtils.h
+++ b/dom/canvas/WebGLContextUtils.h
@@ -62,17 +62,17 @@ WebGLContext::WebGLObjectAsJSValue(JSCon
                                    ErrorResult& rv) const
 {
     if (!object)
         return JS::NullValue();
 
     MOZ_ASSERT(this == object->mContext);
     JS::Rooted<JS::Value> v(cx);
     JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
-    JSAutoCompartment ac(cx, wrapper);
+    JSAutoRealm ar(cx, wrapper);
     if (!dom::GetOrCreateDOMReflector(cx, const_cast<WebGLObjectType*>(object), &v)) {
         rv.Throw(NS_ERROR_FAILURE);
         return JS::NullValue();
     }
     return v;
 }
 
 template <typename WebGLObjectType>
--- a/dom/clients/manager/ClientOpenWindowUtils.cpp
+++ b/dom/clients/manager/ClientOpenWindowUtils.cpp
@@ -193,17 +193,17 @@ OpenWindow(const ClientOpenWindowArgs& a
     MOZ_DIAGNOSTIC_ASSERT(xpc);
 
     JS::Rooted<JSObject*> sandbox(cx);
     rv = xpc->CreateSandbox(cx, principal, sandbox.address());
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return NS_ERROR_TYPE_ERR;
     }
 
-    JSAutoCompartment ac(cx, sandbox);
+    JSAutoRealm ar(cx, sandbox);
 
     // ContentProcess
     nsCOMPtr<nsIWindowWatcher> wwatch =
       do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch));
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -638,17 +638,17 @@ private:
     if (NS_WARN_IF(!global)) {
       return;
     }
 
     // The CreateSandbox call returns a proxy to the actual sandbox object. We
     // don't need a proxy here.
     global = js::UncheckedUnwrap(global);
 
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     // We don't need to set a parent object in mCallData bacause there are not
     // DOM objects exposed to worklet.
 
     ProcessCallData(cx, mConsole, mCallData);
   }
 
   virtual void
@@ -753,17 +753,17 @@ protected:
     if (NS_WARN_IF(!global)) {
       return;
     }
 
     // The GetOrCreateSandbox call returns a proxy to the actual sandbox object.
     // We don't need a proxy here.
     global = js::UncheckedUnwrap(global);
 
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     RunConsole(cx, nullptr, nullptr);
   }
 
   void
   RunBackOnWorkerThreadForCleanup() override
   {
     mWorkerPrivate->AssertIsOnWorkerThread();
@@ -916,17 +916,17 @@ private:
     if (NS_WARN_IF(!global)) {
       return;
     }
 
     // The CreateSandbox call returns a proxy to the actual sandbox object. We
     // don't need a proxy here.
     global = js::UncheckedUnwrap(global);
 
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     // We don't need to set a parent object in mCallData bacause there are not
     // DOM objects exposed to worklet.
 
     ProcessProfileData(cx, mConsole, mName, mAction);
   }
 
   virtual void
@@ -1899,17 +1899,17 @@ Console::PopulateConsoleNotificationInTh
                                             aData->mLogTimerStatus);
   }
 
   else if (aData->mMethodName == MethodCount) {
     event.mCounter = CreateCounterValue(aCx, aData->mCountLabel,
                                         aData->mCountValue);
   }
 
-  JSAutoCompartment ac2(aCx, targetScope);
+  JSAutoRealm ar2(aCx, targetScope);
 
   if (NS_WARN_IF(!ToJSValue(aCx, event, aEventValue))) {
     return false;
   }
 
   JS::Rooted<JSObject*> eventObj(aCx, &aEventValue.toObject());
   if (NS_WARN_IF(!JS_DefineProperty(aCx, eventObj, "wrappedJSObject", eventObj,
                                     JSPROP_ENUMERATE))) {
@@ -2665,17 +2665,17 @@ Console::RetrieveConsoleEvents(JSContext
   MOZ_ASSERT(!NS_IsMainThread());
 
   JS::Rooted<JSObject*> targetScope(aCx, JS::CurrentGlobalOrNull(aCx));
 
   for (uint32_t i = 0; i < mCallDataStorage.Length(); ++i) {
     JS::Rooted<JS::Value> value(aCx);
 
     JS::Rooted<JSObject*> sequenceScope(aCx, mCallDataStorage[i]->mGlobal);
-    JSAutoCompartment ac(aCx, sequenceScope);
+    JSAutoRealm ar(aCx, sequenceScope);
 
     Sequence<JS::Value> sequence;
     SequenceRooter<JS::Value> arguments(aCx, &sequence);
 
     if (!mCallDataStorage[i]->PopulateArgumentsSequence(sequence)) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
--- a/dom/console/ConsoleUtils.cpp
+++ b/dom/console/ConsoleUtils.cpp
@@ -75,17 +75,17 @@ ConsoleUtils::ReportForServiceWorkerScop
   if (NS_WARN_IF(!global)) {
     return;
   }
 
   // The GetOrCreateSandbox call returns a proxy to the actual sandbox object.
   // We don't need a proxy here.
   global = js::UncheckedUnwrap(global);
 
-  JSAutoCompartment ac(cx, global);
+  JSAutoRealm ar(cx, global);
 
   RootedDictionary<ConsoleEvent> event(cx);
 
   event.mID.Construct();
   event.mID.Value().SetAsString() = aScope;
 
   event.mInnerID.Construct();
   event.mInnerID.Value().SetAsString() = NS_LITERAL_STRING("ServiceWorker");
--- a/dom/encoding/TextEncoder.cpp
+++ b/dom/encoding/TextEncoder.cpp
@@ -26,17 +26,17 @@ TextEncoder::Encode(JSContext* aCx,
   nsresult rv;
   const Encoding* ignored;
   Tie(rv, ignored) = UTF_8_ENCODING->Encode(aString, utf8);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
-  JSAutoCompartment ac(aCx, aObj);
+  JSAutoRealm ar(aCx, aObj);
   JSObject* outView = Uint8Array::Create(
     aCx, utf8.Length(), reinterpret_cast<const uint8_t*>(utf8.BeginReading()));
   if (!outView) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
   aRetval.set(outView);
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -1020,32 +1020,32 @@ EventListenerManager::CompileEventHandle
                                    typeAtom, win,
                                    &argCount, &argNames);
 
   // Wrap the event target, so that we can use it as the scope for the event
   // handler. Note that mTarget is different from aElement in the <body> case,
   // where mTarget is a Window.
   //
   // The wrapScope doesn't really matter here, because the target will create
-  // its reflector in the proper scope, and then we'll enter that compartment.
+  // its reflector in the proper scope, and then we'll enter that realm.
   JS::Rooted<JSObject*> wrapScope(cx, global->GetGlobalJSObject());
   JS::Rooted<JS::Value> v(cx);
   {
-    JSAutoCompartment ac(cx, wrapScope);
+    JSAutoRealm ar(cx, wrapScope);
     nsresult rv = nsContentUtils::WrapNative(cx, mTarget, &v,
                                              /* aAllowWrapping = */ false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   JS::Rooted<JSObject*> target(cx, &v.toObject());
-  JSAutoCompartment ac(cx, target);
+  JSAutoRealm ar(cx, target);
 
-  // Now that we've entered the compartment we actually care about, create our
+  // Now that we've entered the realm we actually care about, create our
   // scope chain.  Note that we start with |element|, not aElement, because
   // mTarget is different from aElement in the <body> case, where mTarget is a
   // Window, and in that case we do not want the scope chain to include the body
   // or the document.
   JS::AutoObjectVector scopeChain(cx);
   if (!nsJSUtils::GetScopeChainForElement(cx, element, scopeChain)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
--- a/dom/events/EventListenerService.cpp
+++ b/dom/events/EventListenerService.cpp
@@ -147,51 +147,51 @@ EventListenerInfo::GetInSystemEventGroup
   *aInSystemEventGroup = mInSystemEventGroup;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 EventListenerInfo::GetListenerObject(JSContext* aCx,
                                      JS::MutableHandle<JS::Value> aObject)
 {
-  Maybe<JSAutoCompartment> ac;
-  GetJSVal(aCx, ac, aObject);
+  Maybe<JSAutoRealm> ar;
+  GetJSVal(aCx, ar, aObject);
   return NS_OK;
 }
 
 /******************************************************************************
  * mozilla::EventListenerService
  ******************************************************************************/
 
 NS_IMPL_ISUPPORTS(EventListenerService, nsIEventListenerService)
 
 bool
 EventListenerInfo::GetJSVal(JSContext* aCx,
-                            Maybe<JSAutoCompartment>& aAc,
+                            Maybe<JSAutoRealm>& aAr,
                             JS::MutableHandle<JS::Value> aJSVal)
 {
   if (mScriptedListener) {
     aJSVal.setObject(*mScriptedListener);
-    aAc.emplace(aCx, mScriptedListener);
+    aAr.emplace(aCx, mScriptedListener);
     return true;
   }
 
   aJSVal.setNull();
   return false;
 }
 
 NS_IMETHODIMP
 EventListenerInfo::ToSource(nsAString& aResult)
 {
   aResult.SetIsVoid(true);
 
   AutoSafeJSContext cx;
-  Maybe<JSAutoCompartment> ac;
+  Maybe<JSAutoRealm> ar;
   JS::Rooted<JS::Value> v(cx);
-  if (GetJSVal(cx, ac, &v)) {
+  if (GetJSVal(cx, ar, &v)) {
     JSString* str = JS_ValueToSource(cx, v);
     if (str) {
       nsAutoJSString autoStr;
       if (autoStr.init(cx, str)) {
         aResult.Assign(autoStr);
       }
     }
   }
--- a/dom/events/EventListenerService.h
+++ b/dom/events/EventListenerService.h
@@ -56,17 +56,17 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(EventListenerInfo)
   NS_DECL_NSIEVENTLISTENERINFO
 
 protected:
  virtual ~EventListenerInfo();
 
   bool GetJSVal(JSContext* aCx,
-                Maybe<JSAutoCompartment>& aAc,
+                Maybe<JSAutoRealm>& aAr,
                 JS::MutableHandle<JS::Value> aJSVal);
 
   nsString mType;
   JS::Heap<JSObject*> mScriptedListener;  // May be null.
   bool mCapturing;
   bool mAllowsUntrusted;
   bool mInSystemEventGroup;
 };
--- a/dom/file/nsHostObjectProtocolHandler.cpp
+++ b/dom/file/nsHostObjectProtocolHandler.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsHostObjectProtocolHandler.h"
 
-#include "DOMMediaStream.h"
 #include "mozilla/dom/ChromeUtils.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/Exceptions.h"
 #include "mozilla/dom/BlobImpl.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/MediaSource.h"
 #include "mozilla/ipc/IPCStreamUtils.h"
@@ -37,45 +36,36 @@ using namespace mozilla::dom;
 using namespace mozilla::ipc;
 
 // -----------------------------------------------------------------------
 // Hash table
 struct DataInfo
 {
   enum ObjectType {
     eBlobImpl,
-    eMediaStream,
     eMediaSource
   };
 
   DataInfo(BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal)
     : mObjectType(eBlobImpl)
     , mBlobImpl(aBlobImpl)
     , mPrincipal(aPrincipal)
     , mRevoked(false)
   {}
 
-  DataInfo(DOMMediaStream* aMediaStream, nsIPrincipal* aPrincipal)
-    : mObjectType(eMediaStream)
-    , mMediaStream(aMediaStream)
-    , mPrincipal(aPrincipal)
-    , mRevoked(false)
-  {}
-
   DataInfo(MediaSource* aMediaSource, nsIPrincipal* aPrincipal)
     : mObjectType(eMediaSource)
     , mMediaSource(aMediaSource)
     , mPrincipal(aPrincipal)
     , mRevoked(false)
   {}
 
   ObjectType mObjectType;
 
   RefPtr<BlobImpl> mBlobImpl;
-  RefPtr<DOMMediaStream> mMediaStream;
   RefPtr<MediaSource> mMediaSource;
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCString mStack;
 
   // When a blobURL is revoked, we keep it alive for RELEASING_TIMER
   // milliseconds in order to support pending operations such as navigation,
   // download and so on.
@@ -303,20 +293,19 @@ class BlobURLsReporter final : public ns
               UNITS_COUNT,
               1,
               descString,
               aData);
         }
         continue;
       }
 
-      // Just report the path for the DOMMediaStream or MediaSource.
+      // Just report the path for the MediaSource.
       nsAutoCString path;
-      path = iter.UserData()->mObjectType == DataInfo::eMediaSource
-               ? "media-source-urls/" : "dom-media-stream-urls/";
+      path = "media-source-urls/";
       BuildPath(path, key, info, aAnonymize);
 
       NS_NAMED_LITERAL_CSTRING(desc,
         "An object URL allocated with URL.createObjectURL; the referenced "
         "data cannot be freed until all URLs for it have been explicitly "
         "invalidated with URL.revokeObjectURL.");
 
       aCallback->Callback(EmptyCString(), path, KIND_OTHER, UNITS_COUNT, 1,
@@ -625,32 +614,16 @@ nsHostObjectProtocolHandler::AddDataEntr
   rv = AddDataEntryInternal(aUri, aBlobImpl, aPrincipal);
   NS_ENSURE_SUCCESS(rv, rv);
 
   BroadcastBlobURLRegistration(aUri, aBlobImpl, aPrincipal);
   return NS_OK;
 }
 
 /* static */ nsresult
-nsHostObjectProtocolHandler::AddDataEntry(DOMMediaStream* aMediaStream,
-                                          nsIPrincipal* aPrincipal,
-                                          nsACString& aUri)
-{
-  Init();
-
-  nsresult rv = GenerateURIStringForBlobURL(aPrincipal, aUri);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = AddDataEntryInternal(aUri, aMediaStream, aPrincipal);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
-}
-
-/* static */ nsresult
 nsHostObjectProtocolHandler::AddDataEntry(MediaSource* aMediaSource,
                                           nsIPrincipal* aPrincipal,
                                           nsACString& aUri)
 {
   Init();
 
   nsresult rv = GenerateURIStringForBlobURL(aPrincipal, aUri);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -819,19 +792,16 @@ nsHostObjectProtocolHandler::Traverse(co
     return;
   }
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCallback, "HostObjectProtocolHandler DataInfo.mBlobImpl");
   aCallback.NoteXPCOMChild(res->mBlobImpl);
 
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCallback, "HostObjectProtocolHandler DataInfo.mMediaSource");
   aCallback.NoteXPCOMChild(res->mMediaSource);
-
-  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCallback, "HostObjectProtocolHandler DataInfo.mMediaStream");
-  aCallback.NoteXPCOMChild(res->mMediaStream);
 }
 
 // -----------------------------------------------------------------------
 // Protocol handler
 
 NS_IMPL_ISUPPORTS(nsHostObjectProtocolHandler, nsIProtocolHandler,
     nsISupportsWeakReference)
 
@@ -1069,29 +1039,16 @@ NS_GetStreamForBlobURI(nsIURI* aURI, nsI
   blobImpl->CreateInputStream(aStream, rv);
   if (NS_WARN_IF(rv.Failed())) {
     return rv.StealNSResult();
   }
 
   return NS_OK;
 }
 
-nsresult
-NS_GetStreamForMediaStreamURI(nsIURI* aURI, DOMMediaStream** aStream)
-{
-  DataInfo* info = GetDataInfoFromURI(aURI);
-  if (!info || info->mObjectType != DataInfo::eMediaStream) {
-    return NS_ERROR_DOM_BAD_URI;
-  }
-
-  RefPtr<DOMMediaStream> mediaStream = info->mMediaStream;
-  mediaStream.forget(aStream);
-  return NS_OK;
-}
-
 NS_IMETHODIMP
 nsFontTableProtocolHandler::NewURI(const nsACString& aSpec,
                                    const char *aCharset,
                                    nsIURI *aBaseURI,
                                    nsIURI **aResult)
 {
   nsresult rv;
   nsCOMPtr<nsIURI> uri;
@@ -1182,17 +1139,12 @@ bool IsType(nsIURI* aUri, DataInfo::Obje
   return info->mObjectType == aType;
 }
 
 bool IsBlobURI(nsIURI* aUri)
 {
   return IsType(aUri, DataInfo::eBlobImpl);
 }
 
-bool IsMediaStreamURI(nsIURI* aUri)
-{
-  return IsType(aUri, DataInfo::eMediaStream);
-}
-
 bool IsMediaSourceURI(nsIURI* aUri)
 {
   return IsType(aUri, DataInfo::eMediaSource);
 }
--- a/dom/file/nsHostObjectProtocolHandler.h
+++ b/dom/file/nsHostObjectProtocolHandler.h
@@ -18,17 +18,16 @@
 #define BLOBURI_SCHEME "blob"
 #define FONTTABLEURI_SCHEME "moz-fonttable"
 #define RTSPURI_SCHEME "rtsp"
 
 class nsIPrincipal;
 
 namespace mozilla {
 class BlobURLsReporter;
-class DOMMediaStream;
 
 namespace dom {
 class BlobImpl;
 class BlobURLRegistrationData;
 class ContentParent;
 class MediaSource;
 } // namespace dom
 } // namespace mozilla
@@ -60,19 +59,16 @@ public:
   static nsresult GenerateURIStringForBlobURL(nsIPrincipal* aPrincipal,
                                               nsACString &aUri);
 
   // Methods for managing uri->object mapping
   // AddDataEntry creates the URI with the given scheme and returns it in aUri
   static nsresult AddDataEntry(mozilla::dom::BlobImpl* aBlobImpl,
                                nsIPrincipal* aPrincipal,
                                nsACString& aUri);
-  static nsresult AddDataEntry(mozilla::DOMMediaStream* aMediaStream,
-                               nsIPrincipal* aPrincipal,
-                               nsACString& aUri);
   static nsresult AddDataEntry(mozilla::dom::MediaSource* aMediaSource,
                                nsIPrincipal* aPrincipal,
                                nsACString& aUri);
   // IPC only
   static nsresult AddDataEntry(const nsACString& aURI,
                                nsIPrincipal* aPrincipal,
                                mozilla::dom::BlobImpl* aBlobImpl);
 
@@ -111,17 +107,16 @@ public:
   NS_IMETHOD GetScheme(nsACString &result) override;
   NS_IMETHOD NewURI(const nsACString & aSpec,
                     const char *aOriginCharset,
                     nsIURI *aBaseURI,
                     nsIURI **_retval) override;
 };
 
 bool IsBlobURI(nsIURI* aUri);
-bool IsMediaStreamURI(nsIURI* aUri);
 bool IsMediaSourceURI(nsIURI* aUri);
 
 inline bool IsRtspURI(nsIURI* aUri)
 {
   bool isRtsp;
   return NS_SUCCEEDED(aUri->SchemeIs(RTSPURI_SCHEME, &isRtsp)) && isRtsp;
 }
 
@@ -136,14 +131,11 @@ NS_GetBlobForBlobURI(nsIURI* aURI, mozil
 
 extern nsresult
 NS_GetBlobForBlobURISpec(const nsACString& aSpec, mozilla::dom::BlobImpl** aBlob);
 
 extern nsresult
 NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream);
 
 extern nsresult
-NS_GetStreamForMediaStreamURI(nsIURI* aURI, mozilla::DOMMediaStream** aStream);
-
-extern nsresult
 NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource);
 
 #endif /* nsHostObjectProtocolHandler_h */
--- a/dom/file/nsHostObjectURI.h
+++ b/dom/file/nsHostObjectURI.h
@@ -14,19 +14,18 @@
 #include "nsIPrincipal.h"
 #include "nsISerializable.h"
 #include "nsIURIWithPrincipal.h"
 #include "nsSimpleURI.h"
 #include "nsIIPCSerializableURI.h"
 #include "nsProxyRelease.h"
 
 /**
- * These URIs refer to host objects: Blobs, with scheme "blob",
- * MediaStreams, with scheme "mediastream", and MediaSources, with scheme
- * "mediasource".
+ * These URIs refer to host objects with "blob" scheme. The underlying objects
+ * can be Blobs or MediaSources.
  */
 class nsHostObjectURI final
   : public mozilla::net::nsSimpleURI
   , public nsIURIWithPrincipal
 {
 private:
   explicit nsHostObjectURI(nsIPrincipal* aPrincipal)
     : mozilla::net::nsSimpleURI()
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2091,18 +2091,17 @@ void HTMLMediaElement::SelectResource()
       mLoadingSrc = uri;
       mLoadingSrcTriggeringPrincipal = mSrcAttrTriggeringPrincipal;
       DDLOG(DDLogCategory::Property,
             "loading_src",
             nsCString(NS_ConvertUTF16toUTF8(src)));
       mMediaSource = mSrcMediaSource;
       DDLINKCHILD("mediasource", mMediaSource.get());
       UpdatePreloadAction();
-      if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE &&
-          !IsMediaStreamURI(mLoadingSrc) && !mMediaSource) {
+      if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE && !mMediaSource) {
         // preload:none media, suspend the load here before we make any
         // network requests.
         SuspendLoad();
         return;
       }
 
       rv = LoadResource();
       if (NS_SUCCEEDED(rv)) {
@@ -2421,18 +2420,17 @@ void HTMLMediaElement::LoadFromSourceChi
     DDLOG(DDLogCategory::Property,
           "loading_src",
           nsCString(NS_ConvertUTF16toUTF8(src)));
     mMediaSource = childSrc->GetSrcMediaSource();
     DDLINKCHILD("mediasource", mMediaSource.get());
     NS_ASSERTION(mNetworkState == NETWORK_LOADING,
                  "Network state should be loading");
 
-    if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE &&
-        !IsMediaStreamURI(mLoadingSrc) && !mMediaSource) {
+    if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE && !mMediaSource) {
       // preload:none media, suspend the load here before we make any
       // network requests.
       SuspendLoad();
       return;
     }
 
     if (NS_SUCCEEDED(LoadResource())) {
       return;
@@ -2571,30 +2569,16 @@ HTMLMediaElement::LoadResource()
     // Clone it.
     // TODO: remove the cast by storing ChannelMediaDecoder in the URI table.
     nsresult rv = InitializeDecoderAsClone(
       static_cast<ChannelMediaDecoder*>(other->mDecoder.get()));
     if (NS_SUCCEEDED(rv))
       return rv;
   }
 
-  if (IsMediaStreamURI(mLoadingSrc)) {
-    RefPtr<DOMMediaStream> stream;
-    nsresult rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, getter_AddRefs(stream));
-    if (NS_FAILED(rv)) {
-      nsAutoString spec;
-      GetCurrentSrc(spec);
-      const char16_t* params[] = { spec.get() };
-      ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
-      return MediaResult(rv, "MediaLoadInvalidURI");
-    }
-    SetupSrcMediaStreamPlayback(stream);
-    return NS_OK;
-  }
-
   if (mMediaSource) {
     MediaDecoderInit decoderInit(
       this,
       mMuted ? 0.0 : mVolume,
       mPreservesPitch,
       mPlaybackRate,
       mPreloadAction == HTMLMediaElement::PRELOAD_METADATA,
       mHasSuspendTaint,
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1446,17 +1446,17 @@ nsHTMLDocument::Open(JSContext* cx,
     // Now make sure we're not flagged as the initial document anymore, now
     // that we've had stuff done to us.  From now on, if anyone tries to
     // document.open() us, they get a new inner window.
     SetIsInitialDocument(false);
 
     nsCOMPtr<nsIScriptGlobalObject> newScope(do_QueryReferent(mScopeObject));
     JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
     if (oldScope && newScope != oldScope && wrapper) {
-      JSAutoCompartment ac(cx, wrapper);
+      JSAutoRealm ar(cx, wrapper);
       mozilla::dom::ReparentWrapper(cx, wrapper, aError);
       if (aError.Failed()) {
         return nullptr;
       }
 
       // Also reparent the template contents owner document
       // because its global is set to the same as this document.
       if (mTemplateContentsOwner) {
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1462,17 +1462,17 @@ public:
     JSContext* cx = jsapi.cx();
 
     JS::Rooted<JSObject*> global(cx, SandboxHolder::GetSandbox(cx));
     if (NS_WARN_IF(!global)) {
       OperationCompleted(NS_ERROR_FAILURE);
       return NS_OK;
     }
 
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     JS::Rooted<JS::Value> value(cx);
     nsresult rv = DeserializeIndexValue(cx, &value);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       OperationCompleted(rv);
       return NS_OK;
     }
 
@@ -1584,17 +1584,17 @@ public:
     JSContext* cx = jsapi.cx();
 
     JS::Rooted<JSObject*> global(cx, SandboxHolder::GetSandbox(cx));
     if (NS_WARN_IF(!global)) {
       OperationCompleted(NS_ERROR_FAILURE);
       return NS_OK;
     }
 
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     JS::Rooted<JS::Value> value(cx);
     nsresult rv = DeserializeUpgradeValue(cx, &value);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       OperationCompleted(rv);
       return NS_OK;
     }
 
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -311,23 +311,23 @@ IDBRequest::SetResultCallback(ResultCall
 
   // See if our window is still valid.
   if (NS_WARN_IF(NS_FAILED(CheckInnerWindowCorrectness()))) {
     SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     return;
   }
 
   AutoJSAPI autoJS;
-  Maybe<JSAutoCompartment> ac;
+  Maybe<JSAutoRealm> ar;
 
   if (GetScriptOwner()) {
     // If we have a script owner we want the SafeJSContext and then to enter the
-    // script owner's compartment.
+    // script owner's realm.
     autoJS.Init();
-    ac.emplace(autoJS.cx(), GetScriptOwner());
+    ar.emplace(autoJS.cx(), GetScriptOwner());
   } else {
     // Otherwise our owner is a window and we use that to initialize.
     MOZ_ASSERT(GetOwner());
     if (!autoJS.Init(GetOwner())) {
       IDB_WARNING("Failed to initialize AutoJSAPI!");
       SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
       return;
     }
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -467,17 +467,17 @@ ConsoleListener::Observe(nsIConsoleMessa
       jsapi.Init();
       JSContext* cx = jsapi.cx();
 
       JS::RootedValue stack(cx);
       rv = scriptError->GetStack(&stack);
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (stack.isObject()) {
-        JSAutoCompartment ac(cx, &stack.toObject());
+        JSAutoRealm ar(cx, &stack.toObject());
 
         StructuredCloneData data;
         ErrorResult err;
         data.Write(cx, stack, err);
         if (err.Failed()) {
           return err.StealNSResult();
         }
 
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -1131,19 +1131,16 @@ skip-if = toolkit == 'android' # bug 137
 [test_streams_autoplay.html]
 tags=msg capturestream
 [test_streams_capture_origin.html]
 skip-if = toolkit == 'android' # bug 1372457
 tags=msg capturestream
 [test_streams_element_capture.html]
 skip-if = toolkit == 'android' # bug 1372457
 tags=msg capturestream
-[test_streams_element_capture_createObjectURL.html]
-skip-if = android_version == '15' || android_version == '17' || (android_version == '19' && debug) # android(bug 1232305)
-tags=msg capturestream
 [test_streams_element_capture_playback.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 tags=msg capturestream
 [test_streams_element_capture_reset.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 tags=msg capturestream
 [test_streams_gc.html]
 skip-if = android_version == '15' || android_version == '17' || (android_version == '19' && debug) # android(bug 1232305)
deleted file mode 100644
--- a/dom/media/test/test_streams_element_capture_createObjectURL.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test that a MediaStream captured from one element plays back in another</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  <script type="text/javascript" src="manifest.js"></script>
-</head>
-<body>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-SimpleTest.waitForExplicitFinish();
-
-var manager = new MediaTestManager;
-
-function checkDrawImage(vout) {
-  var canvas = document.createElement("canvas");
-  var ctx = canvas.getContext("2d");
-  ctx.drawImage(vout, 0, 0);
-  var imgData = ctx.getImageData(0, 0, 1, 1);
-  is(imgData.data[3], 255, "Check video frame pixel has been drawn");
-}
-
-function isGreaterThanOrEqualEps(a, b, msg) {
-  ok(a >= b - 0.01,
-     "Got " + a + ", expected at least " + b + "; " + msg);
-}
-
-function startTest(test, token) {
-  manager.started(token);
-
-  var v = document.createElement('video');
-  var vout = document.createElement('video');
-  vout.token = token;
-
-  v.src = test.name;
-  v.preload = "metadata"
-  var stream;
-
-  var checkEnded = function() {
-    is(stream.currentTime, vout.currentTime, test.name + " stream final currentTime");
-    if (test.duration) {
-      isGreaterThanOrEqualEps(vout.currentTime, test.duration,
-         test.name + " current time at end");
-    }
-    is(vout.readyState, vout.HAVE_CURRENT_DATA, test.name + " checking readyState");
-    ok(vout.ended, test.name + " checking playback has ended");
-    if (test.type.match(/^video/)) {
-      checkDrawImage(vout);
-    }
-    vout.remove();
-    URL.revokeObjectURL(vout.src);
-    manager.finished(vout.token);
-  };
-  vout.addEventListener("ended", checkEnded);
-
-  document.body.appendChild(vout);
-  v.onloadedmetadata = function () {
-    stream = v.mozCaptureStreamUntilEnded();
-    is(stream.currentTime, 0, test.name + " stream initial currentTime");
-    vout.src = URL.createObjectURL(stream);
-    v.play();
-    vout.play();
-  };
-}
-
-SpecialPowers.pushPrefEnv(
-  { "set": [["privacy.reduceTimerPrecision", false]]},
-  function() {
-    manager.runTests([getPlayableVideo(gSmallTests)], startTest);
-  });
-</script>
-</pre>
-</body>
-</html>
--- a/dom/media/test/test_streams_individual_pause.html
+++ b/dom/media/test/test_streams_individual_pause.html
@@ -26,19 +26,18 @@ async function startTest() {
   try {
     // This test expects fake devices so that the video color will change
     // over time, explicitly request fakes.
     await pushGetUserMediaTestPrefs({fakeAudio: true, fakeVideo: true});
     let stream = await navigator.mediaDevices.getUserMedia({video: true});
     let video1 = document.getElementById('video1');
     let video2 = document.getElementById('video2');
 
-    let src = URL.createObjectURL(stream);
-    video1.src = src;
-    video2.src = src;
+    video1.srcObject = stream;
+    video2.srcObject = stream;
 
     video1.onplaying = () => video1.pause();
 
     let v1PausedImageData;
     let v2PausedImageData;
 
     video1.onpause = function() {
       v1PausedImageData = getVideoImagePixelData(video1);
--- a/dom/media/test/test_video_dimensions.html
+++ b/dom/media/test/test_video_dimensions.html
@@ -49,17 +49,17 @@ var startTest = function(test, token) {
 
     numVideoElementsFinished += 1;
     if (v === v1) {
       removeNodeAndSource(v1);
       v2.load();
     }
 
     if (v === v2) {
-      vout.src = URL.createObjectURL(v2.mozCaptureStreamUntilEnded());
+      vout.srcObject = v2.mozCaptureStreamUntilEnded();
       v2.play();
       vout.play();
     }
 
     if (numVideoElementsFinished === 3) {
       removeNodeAndSource(v2);
       removeNodeAndSource(vout);
       manager.finished(token);
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -530,17 +530,17 @@ AudioContext::DecodeAudioData(const Arra
                               const Optional<OwningNonNull<DecodeErrorCallback> >& aFailureCallback,
                               ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(GetParentObject());
   RefPtr<Promise> promise;
   AutoJSAPI jsapi;
   jsapi.Init();
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, aBuffer.Obj());
+  JSAutoRealm ar(cx, aBuffer.Obj());
 
   promise = Promise::Create(parentObject, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   aBuffer.ComputeLengthAndData();
 
--- a/dom/network/TCPSocket.cpp
+++ b/dom/network/TCPSocket.cpp
@@ -854,17 +854,17 @@ TCPSocket::Send(JSContext* aCx,
   if (mSocketBridgeChild) {
     nsresult rv = mSocketBridgeChild->SendSend(aData, aByteOffset, byteLength, ++mTrackingNumber);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       aRv.Throw(rv);
       return false;
     }
   } else {
     JS::Rooted<JSObject*> obj(aCx, aData.Obj());
-    JSAutoCompartment ac(aCx, obj);
+    JSAutoRealm ar(aCx, obj);
     JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*obj));
 
     stream = do_CreateInstance("@mozilla.org/io/arraybuffer-input-stream;1");
     nsresult rv = stream->SetData(value, aByteOffset, byteLength, aCx);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       aRv.Throw(rv);
       return false;
     }
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -733,17 +733,17 @@ nsJSObjWrapper::NP_HasMethod(NPObject *n
     ThrowJSExceptionASCII(cx,
                           "Null npobj in nsJSObjWrapper::NP_HasMethod!");
 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
 
-  JSAutoCompartment ac(cx, npjsobj->mJSObj);
+  JSAutoRealm ar(cx, npjsobj->mJSObj);
   MarkCrossZoneNPIdentifier(cx, id);
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
 
   JS::Rooted<JS::Value> v(cx);
   bool ok = GetProperty(cx, npjsobj->mJSObj, id, &v);
 
   return ok && !v.isPrimitive() &&
@@ -773,17 +773,17 @@ doInvoke(NPObject *npobj, NPIdentifier m
   }
 
   // Initialize *result
   VOID_TO_NPVARIANT(*result);
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
 
   JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
-  JSAutoCompartment ac(cx, jsobj);
+  JSAutoRealm ar(cx, jsobj);
   MarkCrossZoneNPIdentifier(cx, method);
   JS::Rooted<JS::Value> fv(cx);
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
 
   if (method != NPIdentifier_VOID) {
     if (!GetProperty(cx, jsobj, method, &fv) ||
         ::JS_TypeOfValue(cx, fv) != JSTYPE_FUNCTION) {
@@ -866,17 +866,17 @@ nsJSObjWrapper::NP_HasProperty(NPObject 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
   bool found, ok = false;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
   JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
-  JSAutoCompartment ac(cx, jsobj);
+  JSAutoRealm ar(cx, jsobj);
   MarkCrossZoneNPIdentifier(cx, npid);
 
   NS_ASSERTION(NPIdentifierIsInt(npid) || NPIdentifierIsString(npid),
                "id must be either string or int!\n");
   JS::Rooted<jsid> id(cx, NPIdentifierToJSId(npid));
   ok = ::JS_HasPropertyById(cx, jsobj, id, &found);
   return ok && found;
 }
@@ -903,17 +903,17 @@ nsJSObjWrapper::NP_GetProperty(NPObject 
                           "Null npobj in nsJSObjWrapper::NP_GetProperty!");
 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
-  JSAutoCompartment ac(cx, npjsobj->mJSObj);
+  JSAutoRealm ar(cx, npjsobj->mJSObj);
   MarkCrossZoneNPIdentifier(cx, id);
 
   JS::Rooted<JS::Value> v(cx);
   return (GetProperty(cx, npjsobj->mJSObj, id, &v) &&
           JSValToNPVariant(npp, cx, v, result));
 }
 
 // static
@@ -940,17 +940,17 @@ nsJSObjWrapper::NP_SetProperty(NPObject 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
   bool ok = false;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
   JS::Rooted<JSObject*> jsObj(cx, npjsobj->mJSObj);
-  JSAutoCompartment ac(cx, jsObj);
+  JSAutoRealm ar(cx, jsObj);
   MarkCrossZoneNPIdentifier(cx, npid);
 
   JS::Rooted<JS::Value> v(cx, NPVariantToJSVal(npp, cx, value));
 
   NS_ASSERTION(NPIdentifierIsInt(npid) || NPIdentifierIsString(npid),
                "id must be either string or int!\n");
   JS::Rooted<jsid> id(cx, NPIdentifierToJSId(npid));
   ok = ::JS_SetPropertyById(cx, jsObj, id, v);
@@ -978,17 +978,17 @@ nsJSObjWrapper::NP_RemoveProperty(NPObje
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
   JS::ObjectOpResult result;
   JS::Rooted<JSObject*> obj(cx, npjsobj->mJSObj);
-  JSAutoCompartment ac(cx, obj);
+  JSAutoRealm ar(cx, obj);
   MarkCrossZoneNPIdentifier(cx, npid);
 
   NS_ASSERTION(NPIdentifierIsInt(npid) || NPIdentifierIsString(npid),
                "id must be either string or int!\n");
   JS::Rooted<jsid> id(cx, NPIdentifierToJSId(npid));
   if (!::JS_DeletePropertyById(cx, obj, id, result))
     return false;
 
@@ -1032,17 +1032,17 @@ nsJSObjWrapper::NP_Enumerate(NPObject *n
 
     return false;
   }
 
   nsJSObjWrapper *npjsobj = (nsJSObjWrapper *)npobj;
 
   AutoJSExceptionSuppressor suppressor(aes, npjsobj);
   JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
-  JSAutoCompartment ac(cx, jsobj);
+  JSAutoRealm ar(cx, jsobj);
 
   JS::Rooted<JS::IdVector> ida(cx, JS::IdVector(cx));
   if (!JS_Enumerate(cx, jsobj, &ida)) {
     return false;
   }
 
   *count = ida.length();
   *idarray = (NPIdentifier*) malloc(*count * sizeof(NPIdentifier));
@@ -1174,17 +1174,17 @@ GetNPObjectWrapper(JSContext *cx, JS::Ha
   while (obj && (obj = js::CheckedUnwrap(obj))) {
     if (nsNPObjWrapper::IsWrapper(obj)) {
       if (wrapResult && !JS_WrapObject(cx, &obj)) {
         return nullptr;
       }
       return obj;
     }
 
-    JSAutoCompartment ac(cx, obj);
+    JSAutoRealm ar(cx, obj);
     if (!::JS_GetPrototype(cx, obj, &obj)) {
       return nullptr;
     }
   }
   return nullptr;
 }
 
 static NPObject *
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -96,33 +96,33 @@ Promise::Create(nsIGlobalObject* aGlobal
   return p.forget();
 }
 
 // static
 already_AddRefed<Promise>
 Promise::Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
                  JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
-  JSAutoCompartment ac(aCx, aGlobal->GetGlobalJSObject());
+  JSAutoRealm ar(aCx, aGlobal->GetGlobalJSObject());
   JS::Rooted<JSObject*> p(aCx,
                           JS::CallOriginalPromiseResolve(aCx, aValue));
   if (!p) {
     aRv.NoteJSContextException(aCx);
     return nullptr;
   }
 
   return CreateFromExisting(aGlobal, p);
 }
 
 // static
 already_AddRefed<Promise>
 Promise::Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
                 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
-  JSAutoCompartment ac(aCx, aGlobal->GetGlobalJSObject());
+  JSAutoRealm ar(aCx, aGlobal->GetGlobalJSObject());
   JS::Rooted<JSObject*> p(aCx,
                           JS::CallOriginalPromiseReject(aCx, aValue));
   if (!p) {
     aRv.NoteJSContextException(aCx);
     return nullptr;
   }
 
   return CreateFromExisting(aGlobal, p);
--- a/dom/promise/PromiseDebugging.cpp
+++ b/dom/promise/PromiseDebugging.cpp
@@ -274,17 +274,17 @@ PromiseDebugging::FlushUncaughtRejection
     }
 
     for (size_t j = 0; j < observers.Length(); ++j) {
       RefPtr<UncaughtRejectionObserver> obs =
         static_cast<UncaughtRejectionObserver*>(observers[j].get());
 
       obs->OnLeftUncaught(promise, IgnoreErrors());
     }
-    JSAutoCompartment ac(cx, promise);
+    JSAutoRealm ar(cx, promise);
     Promise::ReportRejectedPromise(cx, promise);
   }
   storage->mUncaughtRejections.clear();
 
   // Notify observers of consumed Promise.
 
   for (size_t i = 0; i < consumed.length(); i++) {
     JS::RootedObject promise(cx, consumed[i]);
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -764,70 +764,58 @@ ScriptLoader::StartFetchingModuleAndDepe
     childRequest->mReady.Reject(rv, __func__);
     return ready;
   }
 
   return ready;
 }
 
 // 8.1.3.8.1 HostResolveImportedModule(referencingModule, specifier)
-bool
-HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp)
+JSObject*
+HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
+                          JS::Handle<JSString*> aSpecifier)
 {
-
-  MOZ_ASSERT(argc == 2);
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  JS::Rooted<JSObject*> module(aCx, &args[0].toObject());
-  JS::Rooted<JSString*> specifier(aCx, args[1].toString());
-
   // Let referencing module script be referencingModule.[[HostDefined]].
-  JS::Value value = JS::GetModuleHostDefinedField(module);
+  JS::Value value = JS::GetModuleHostDefinedField(aModule);
   auto script = static_cast<ModuleScript*>(value.toPrivate());
-  MOZ_ASSERT(script->ModuleRecord() == module);
+  MOZ_ASSERT(script->ModuleRecord() == aModule);
 
   // Let url be the result of resolving a module specifier given referencing
   // module script and specifier.
   nsAutoJSString string;
-  if (!string.init(aCx, specifier)) {
-    return false;
+  if (!string.init(aCx, aSpecifier)) {
+    return nullptr;
   }
 
   nsCOMPtr<nsIURI> uri = ResolveModuleSpecifier(script, string);
 
   // This cannot fail because resolving a module specifier must have been
   // previously successful with these same two arguments.
   MOZ_ASSERT(uri, "Failed to resolve previously-resolved module specifier");
 
   // Let resolved module script be moduleMap[url]. (This entry must exist for us
   // to have gotten to this point.)
   ModuleScript* ms = script->Loader()->GetFetchedModule(uri);
   MOZ_ASSERT(ms, "Resolved module not found in module map");
 
   MOZ_ASSERT(!ms->HasParseError());
-
-  *vp = JS::ObjectValue(*ms->ModuleRecord());
-  return true;
+  MOZ_ASSERT(ms->ModuleRecord());
+
+  return ms->ModuleRecord();
 }
 
-static nsresult
+static void
 EnsureModuleResolveHook(JSContext* aCx)
 {
-  if (JS::GetModuleResolveHook(aCx)) {
-    return NS_OK;
+  JSRuntime* rt = JS_GetRuntime(aCx);
+  if (JS::GetModuleResolveHook(rt)) {
+    return;
   }
 
-  JS::Rooted<JSFunction*> func(aCx);
-  func = JS_NewFunction(aCx, HostResolveImportedModule, 2, 0,
-                        "HostResolveImportedModule");
-  if (!func) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JS::SetModuleResolveHook(aCx, func);
-  return NS_OK;
+  JS::SetModuleResolveHook(rt, HostResolveImportedModule);
 }
 
 void
 ScriptLoader::CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest)
 {
   LOG(("ScriptLoadRequest (%p): Check dependencies loaded", aRequest));
 
   RefPtr<ModuleScript> moduleScript = aRequest->mModuleScript;
@@ -939,18 +927,17 @@ ScriptLoader::InstantiateModuleTree(Modu
   MOZ_ASSERT(moduleScript->ModuleRecord());
 
   nsAutoMicroTask mt;
   AutoJSAPI jsapi;
   if (NS_WARN_IF(!jsapi.Init(moduleScript->ModuleRecord()))) {
     return false;
   }
 
-  nsresult rv = EnsureModuleResolveHook(jsapi.cx());
-  NS_ENSURE_SUCCESS(rv, false);
+  EnsureModuleResolveHook(jsapi.cx());
 
   JS::Rooted<JSObject*> module(jsapi.cx(), moduleScript->ModuleRecord());
   bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), module));
 
   if (!ok) {
     LOG(("ScriptLoadRequest (%p): Instantiate failed", aRequest));
     MOZ_ASSERT(jsapi.HasException());
     JS::RootedValue exception(jsapi.cx());
@@ -2226,18 +2213,17 @@ ScriptLoader::EvaluateScript(ScriptLoadR
       // When a module is already loaded, it is not feched a second time and the
       // mDataType of the request might remain set to DataType::Unknown.
       MOZ_ASSERT(!aRequest->IsBytecode());
       LOG(("ScriptLoadRequest (%p): Evaluate Module", aRequest));
 
       // currentScript is set to null for modules.
       AutoCurrentScriptUpdater scriptUpdater(this, nullptr);
 
-      rv = EnsureModuleResolveHook(cx);
-      NS_ENSURE_SUCCESS(rv, rv);
+      EnsureModuleResolveHook(cx);
 
       ModuleLoadRequest* request = aRequest->AsModuleRequest();
       MOZ_ASSERT(request->mModuleScript);
       MOZ_ASSERT(!request->mOffThreadToken);
 
       ModuleScript* moduleScript = request->mModuleScript;
       if (moduleScript->HasErrorToRethrow()) {
         LOG(("ScriptLoadRequest (%p):   module has error to rethrow", aRequest));
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -500,18 +500,19 @@ private:
                                                       nsresult aResult);
 
   bool IsFetchingModule(ModuleLoadRequest* aRequest) const;
 
   bool ModuleMapContainsURL(nsIURI* aURL) const;
   RefPtr<mozilla::GenericPromise> WaitForModuleFetch(nsIURI* aURL);
   ModuleScript* GetFetchedModule(nsIURI* aURL) const;
 
-  friend bool
-  HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp);
+  friend JSObject*
+  HostResolveImportedModule(JSContext* aCx, JS::Handle<JSObject*> aModule,
+                          JS::Handle<JSString*> aSpecifier);
 
   // Returns wether we should save the bytecode of this script after the
   // execution of the script.
   static bool
   ShouldCacheBytecode(ScriptLoadRequest* aRequest);
 
   nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
   nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
--- a/dom/script/ScriptSettings.cpp
+++ b/dom/script/ScriptSettings.cpp
@@ -352,17 +352,17 @@ AutoJSAPI::InitInternal(nsIGlobalObject*
     // We _could_ just unconditionally emplace mAutoRequest here.  It's just not
     // needed on worker threads, and we're hoping to kill it on the main thread
     // too.
     mAutoRequest.emplace(mCx);
   }
   if (aGlobal) {
     JS::ExposeObjectToActiveJS(aGlobal);
   }
-  mAutoNullableCompartment.emplace(mCx, aGlobal);
+  mAutoNullableRealm.emplace(mCx, aGlobal);
 
   ScriptSettingsStack::Push(this);
 
   mOldWarningReporter.emplace(JS::GetWarningReporter(aCx));
 
   JS::SetWarningReporter(aCx, WarningOnlyErrorReporter);
 
 #ifdef DEBUG
@@ -374,17 +374,17 @@ AutoJSAPI::InitInternal(nsIGlobalObject*
     if (exn.isObject()) {
       JS::Rooted<JSObject*> exnObj(aCx, &exn.toObject());
 
       // Make sure we can actually read things from it.  This UncheckedUwrap is
       // safe because we're only getting data for a debug printf.  In
       // particular, we do not expose this data to anyone, which is very
       // important; otherwise it could be a cross-origin information leak.
       exnObj = js::UncheckedUnwrap(exnObj);
-      JSAutoCompartment ac(aCx, exnObj);
+      JSAutoRealm ar(aCx, exnObj);
 
       nsAutoJSString stack, filename, name, message;
       int32_t line;
 
       JS::Rooted<JS::Value> tmp(aCx);
       if (!JS_GetProperty(aCx, exnObj, "filename", &tmp)) {
         JS_ClearPendingException(aCx);
       }
@@ -551,30 +551,29 @@ WarningOnlyErrorReporter(JSContext* aCx,
 
 void
 AutoJSAPI::ReportException()
 {
   if (!HasException()) {
     return;
   }
 
-  // AutoJSAPI uses a JSAutoNullableCompartment, and may be in a null
-  // compartment when the destructor is called. However, the JS engine
-  // requires us to be in a compartment when we fetch the pending exception.
-  // In this case, we enter the privileged junk scope and don't dispatch any
-  // error events.
+  // AutoJSAPI uses a JSAutoNullableRealm, and may be in a null realm
+  // when the destructor is called. However, the JS engine requires us
+  // to be in a realm when we fetch the pending exception. In this case,
+  // we enter the privileged junk scope and don't dispatch any error events.
   JS::Rooted<JSObject*> errorGlobal(cx(), JS::CurrentGlobalOrNull(cx()));
   if (!errorGlobal) {
     if (mIsMainThread) {
       errorGlobal = xpc::PrivilegedJunkScope();
     } else {
       errorGlobal = GetCurrentThreadWorkerGlobal();
     }
   }
-  JSAutoCompartment ac(cx(), errorGlobal);
+  JSAutoRealm ar(cx(), errorGlobal);
   JS::Rooted<JS::Value> exn(cx());
   js::ErrorReport jsReport(cx());
   if (StealException(&exn) &&
       jsReport.init(cx(), exn, js::ErrorReport::WithSideEffects)) {
     if (mIsMainThread) {
       RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
 
       RefPtr<nsGlobalWindowInner> win = xpc::WindowGlobalOrNull(errorGlobal);
@@ -815,15 +814,15 @@ AutoSlowOperation::AutoSlowOperation(MOZ
   Init();
 }
 
 void
 AutoSlowOperation::CheckForInterrupt()
 {
   // For now we support only main thread!
   if (mIsMainThread) {
-    // JS_CheckForInterrupt expects us to be in a compartment.
-    JSAutoCompartment ac(cx(), xpc::UnprivilegedJunkScope());
+    // JS_CheckForInterrupt expects us to be in a realm.
+    JSAutoRealm ar(cx(), xpc::UnprivilegedJunkScope());
     JS_CheckForInterrupt(cx());
   }
 }
 
 } // namespace mozilla
--- a/dom/script/ScriptSettings.h
+++ b/dom/script/ScriptSettings.h
@@ -289,17 +289,17 @@ public:
   }
 
 protected:
   // Protected constructor for subclasses.  This constructor initialises the
   // AutoJSAPI, so Init must NOT be called on subclasses that use this.
   AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, Type aType);
 
   mozilla::Maybe<JSAutoRequest> mAutoRequest;
-  mozilla::Maybe<JSAutoNullableCompartment> mAutoNullableCompartment;
+  mozilla::Maybe<JSAutoNullableRealm> mAutoNullableRealm;
   JSContext *mCx;
 
   // Whether we're mainthread or not; set when we're initialized.
   bool mIsMainThread;
   Maybe<JS::WarningReporter> mOldWarningReporter;
 
 private:
   void InitInternal(nsIGlobalObject* aGlobalObject, JSObject* aGlobal,
--- a/dom/serviceworkers/ServiceWorkerPrivate.cpp
+++ b/dom/serviceworkers/ServiceWorkerPrivate.cpp
@@ -604,17 +604,17 @@ ServiceWorkerPrivate::SendMessageEvent(i
 
   JS::Rooted<JSObject*> global(cx, sandbox);
   NS_ENSURE_TRUE(sandbox, NS_ERROR_FAILURE);
 
   // The CreateSandbox call returns a proxy to the actual sandbox object.  We
   // don't need a proxy here.
   global = js::UncheckedUnwrap(global);
 
-  JSAutoCompartment ac(cx, global);
+  JSAutoRealm ar(cx, global);
 
   JS::Rooted<JS::Value> messageData(cx);
   aData.Read(cx, &messageData, rv);
   if (rv.Failed()) {
     return rv.StealNSResult();
   }
 
   Sequence<OwningNonNull<MessagePort>> ports;
--- a/dom/url/URL.cpp
+++ b/dom/url/URL.cpp
@@ -59,27 +59,16 @@ URL::CreateObjectURL(const GlobalObject&
   if (NS_IsMainThread()) {
     URLMainThread::CreateObjectURL(aGlobal, aBlob, aResult, aRv);
   } else {
     URLWorker::CreateObjectURL(aGlobal, aBlob, aResult, aRv);
   }
 }
 
 void
-URL::CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
-                     nsAString& aResult, ErrorResult& aRv)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  DeprecationWarning(aGlobal, nsIDocument::eURLCreateObjectURL_MediaStream);
-
-  URLMainThread::CreateObjectURL(aGlobal, aStream, aResult, aRv);
-}
-
-void
 URL::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
                      nsAString& aResult, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   URLMainThread::CreateObjectURL(aGlobal, aSource, aResult, aRv);
 }
 
 void
--- a/dom/url/URL.h
+++ b/dom/url/URL.h
@@ -14,17 +14,16 @@
 #include "nsWrapperCache.h"
 
 class nsISupports;
 class nsIURI;
 
 namespace mozilla {
 
 class ErrorResult;
-class DOMMediaStream;
 
 namespace dom {
 
 class Blob;
 class MediaSource;
 class GlobalObject;
 
 class URL : public URLSearchParamsObserver
@@ -57,20 +56,16 @@ public:
                     const nsAString& aBase, ErrorResult& aRv);
 
 
   static void
   CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
                   nsAString& aResult, ErrorResult& aRv);
 
   static void
-  CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
-                  nsAString& aResult, ErrorResult& aRv);
-
-  static void
   CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
                   nsAString& aResult, ErrorResult& aRv);
 
   static void
   RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aURL,
                   ErrorResult& aRv);
 
   static bool
--- a/dom/url/URLMainThread.cpp
+++ b/dom/url/URLMainThread.cpp
@@ -13,44 +13,16 @@
 #include "nsHostObjectProtocolHandler.h"
 #include "nsIURL.h"
 #include "nsIURIMutator.h"
 #include "nsNetUtil.h"
 
 namespace mozilla {
 namespace dom {
 
-namespace {
-
-template<typename T>
-void
-CreateObjectURLInternal(const GlobalObject& aGlobal, T aObject,
-                        nsAString& aResult, ErrorResult& aRv)
-{
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
-  if (NS_WARN_IF(!global)) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  nsCOMPtr<nsIPrincipal> principal =
-    nsContentUtils::ObjectPrincipal(aGlobal.Get());
-
-  nsAutoCString url;
-  aRv = nsHostObjectProtocolHandler::AddDataEntry(aObject, principal, url);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
-
-  global->RegisterHostObjectURI(url);
-  CopyASCIItoUTF16(url, aResult);
-}
-
-} // anonymous namespace
-
 /* static */ already_AddRefed<URLMainThread>
 URLMainThread::Constructor(const GlobalObject& aGlobal, const nsAString& aURL,
                            const Optional<nsAString>& aBase, ErrorResult& aRv)
 {
   if (aBase.WasPassed()) {
     return Constructor(aGlobal.GetAsSupports(), aURL, aBase.Value(), aRv);
   }
 
@@ -95,26 +67,34 @@ URLMainThread::Constructor(nsISupports* 
   return url.forget();
 }
 
 /* static */ void
 URLMainThread::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
                                nsAString& aResult, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  CreateObjectURLInternal(aGlobal, aBlob.Impl(), aResult, aRv);
-}
+
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
+  if (NS_WARN_IF(!global)) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
-/* static */ void
-URLMainThread::CreateObjectURL(const GlobalObject& aGlobal,
-                               DOMMediaStream& aStream,
-                               nsAString& aResult, ErrorResult& aRv)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  CreateObjectURLInternal(aGlobal, &aStream, aResult, aRv);
+  nsCOMPtr<nsIPrincipal> principal =
+    nsContentUtils::ObjectPrincipal(aGlobal.Get());
+
+  nsAutoCString url;
+  aRv = nsHostObjectProtocolHandler::AddDataEntry(aBlob.Impl(), principal, url);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return;
+  }
+
+  global->RegisterHostObjectURI(url);
+  CopyASCIItoUTF16(url, aResult);
 }
 
 /* static */ void
 URLMainThread::CreateObjectURL(const GlobalObject& aGlobal,
                                MediaSource& aSource,
                                nsAString& aResult, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/url/URLMainThread.h
+++ b/dom/url/URLMainThread.h
@@ -28,20 +28,16 @@ public:
   Constructor(nsISupports* aParent, const nsAString& aURL, nsIURI* aBase,
               ErrorResult& aRv);
 
   static void
   CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
                   nsAString& aResult, ErrorResult& aRv);
 
   static void
-  CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
-                  nsAString& aResult, ErrorResult& aRv);
-
-  static void
   CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
                   nsAString& aResult, ErrorResult& aRv);
 
   static void
   RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aURL,
                   ErrorResult& aRv);
 
   static bool
--- a/dom/webidl/URL.webidl
+++ b/dom/webidl/URL.webidl
@@ -1,17 +1,16 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origins of this IDL file are
  * http://url.spec.whatwg.org/#api
  * http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking
- * http://dev.w3.org/2011/webrtc/editor/getusermedia.html#url
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 [Constructor(USVString url, optional USVString base),
  Exposed=(Window,Worker,WorkerDebugger)]
 interface URL {
@@ -40,18 +39,16 @@ interface URL {
 
   USVString toJSON();
 };
 
 partial interface URL {
   [Throws]
   static DOMString createObjectURL(Blob blob);
   [Throws]
-  static DOMString createObjectURL(MediaStream stream);
-  [Throws]
   static void revokeObjectURL(DOMString url);
   [ChromeOnly, Throws]
   static boolean isValidURL(DOMString url);
 };
 
 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html
 partial interface URL {
   [Throws]
--- a/dom/workers/WorkerDebugger.cpp
+++ b/dom/workers/WorkerDebugger.cpp
@@ -98,17 +98,17 @@ private:
 
     if (NS_WARN_IF(!aWorkerPrivate->EnsureClientSource())) {
       return false;
     }
 
     JS::Rooted<JSObject*> global(aCx, globalScope->GetWrapper());
 
     ErrorResult rv;
-    JSAutoCompartment ac(aCx, global);
+    JSAutoRealm ar(aCx, global);
     workerinternals::LoadMainScript(aWorkerPrivate, mScriptURL,
                                     DebuggerScript, rv);
     rv.WouldReportJSException();
     // Explicitly ignore NS_BINDING_ABORTED on rv.  Or more precisely, still
     // return false and don't SetWorkerScriptExecutedSuccessfully() in that
     // case, but don't throw anything on aCx.  The idea is to not dispatch error
     // events if our load is canceled with that error code.
     if (rv.ErrorCodeIs(NS_BINDING_ABORTED)) {
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -460,22 +460,22 @@ private:
     // because all the other errors are handled when the script is loaded.
     // See: https://dom.spec.whatwg.org/#concept-event-fire
     if (rv.Failed() && !rv.IsJSException()) {
       ReportCompileErrorRunnable::CreateAndDispatch(aCx, aWorkerPrivate);
       rv.SuppressException();
       return false;
     }
 
-    // This is a little dumb, but aCx is in the null compartment here because we
+    // This is a little dumb, but aCx is in the null realm here because we
     // set it up that way in our Run(), since we had not created the global at
-    // that point yet.  So we need to enter the compartment of our global,
+    // that point yet.  So we need to enter the realm of our global,
     // because setting a pending exception on aCx involves wrapping into its
     // current compartment.  Luckily we have a global now.
-    JSAutoCompartment ac(aCx, globalScope->GetGlobalJSObject());
+    JSAutoRealm ar(aCx, globalScope->GetGlobalJSObject());
     if (rv.MaybeSetPendingException(aCx)) {
       return false;
     }
 
     aWorkerPrivate->SetWorkerScriptExecutedSuccessfully();
     return true;
   }
 
@@ -3213,17 +3213,17 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
   AutoJSAPI jsapi;
   jsapi.Init();
   MOZ_ASSERT(jsapi.cx() == aCx);
 
   EnableMemoryReporter();
 
   InitializeGCTimers();
 
-  Maybe<JSAutoCompartment> workerCompartment;
+  Maybe<JSAutoRealm> workerCompartment;
 
   for (;;) {
     WorkerStatus currentStatus, previousStatus;
     bool debuggerRunnablesPending = false;
     bool normalRunnablesPending = false;
 
     {
       MutexAutoLock lock(mMutex);
@@ -3327,27 +3327,27 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
       CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
       ccjs->PerformDebuggerMicroTaskCheckpoint();
 
       if (debuggerRunnablesPending) {
         WorkerDebuggerGlobalScope* globalScope = DebuggerGlobalScope();
         MOZ_ASSERT(globalScope);
 
         // Now *might* be a good time to GC. Let the JS engine make the decision.
-        JSAutoCompartment ac(aCx, globalScope->GetGlobalJSObject());
+        JSAutoRealm ar(aCx, globalScope->GetGlobalJSObject());
         JS_MaybeGC(aCx);
       }
     } else if (normalRunnablesPending) {
       // Process a single runnable from the main queue.
       NS_ProcessNextEvent(mThread, false);
 
       normalRunnablesPending = NS_HasPendingEvents(mThread);
       if (normalRunnablesPending && GlobalScope()) {
         // Now *might* be a good time to GC. Let the JS engine make the decision.
-        JSAutoCompartment ac(aCx, GlobalScope()->GetGlobalJSObject());
+        JSAutoRealm ar(aCx, GlobalScope()->GetGlobalJSObject());
         JS_MaybeGC(aCx);
       }
     }
 
     if (!debuggerRunnablesPending && !normalRunnablesPending) {
       // Both the debugger event queue and the normal event queue has been
       // exhausted, cancel the periodic GC timer and schedule the idle GC timer.
       SetGCTimerMode(IdleTimer);
@@ -5292,17 +5292,17 @@ WorkerPrivate::GetOrCreateGlobalScope(JS
                                      GetServiceWorkerRegistrationDescriptor());
     } else {
       globalScope = new DedicatedWorkerGlobalScope(this, WorkerName());
     }
 
     JS::Rooted<JSObject*> global(aCx);
     NS_ENSURE_TRUE(globalScope->WrapGlobalObject(aCx, &global), nullptr);
 
-    JSAutoCompartment ac(aCx, global);
+    JSAutoRealm ar(aCx, global);
 
     // RegisterBindings() can spin a nested event loop so we have to set mScope
     // before calling it, and we have to make sure to unset mScope if it fails.
     mScope = Move(globalScope);
 
     if (!RegisterBindings(aCx, global)) {
       mScope = nullptr;
       return nullptr;
@@ -5322,17 +5322,17 @@ WorkerPrivate::CreateDebuggerGlobalScope
   MOZ_ASSERT(!mDebuggerScope);
 
   RefPtr<WorkerDebuggerGlobalScope> globalScope =
     new WorkerDebuggerGlobalScope(this);
 
   JS::Rooted<JSObject*> global(aCx);
   NS_ENSURE_TRUE(globalScope->WrapGlobalObject(aCx, &global), nullptr);
 
-  JSAutoCompartment ac(aCx, global);
+  JSAutoRealm ar(aCx, global);
 
   // RegisterDebuggerBindings() can spin a nested event loop so we have to set
   // mDebuggerScope before calling it, and we have to make sure to unset
   // mDebuggerScope if it fails.
   mDebuggerScope = Move(globalScope);
 
   if (!RegisterDebuggerBindings(aCx, global)) {
     mDebuggerScope = nullptr;
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -267,17 +267,17 @@ WorkerRunnable::Run()
 
   bool result = PreRun(mWorkerPrivate);
   if (!result) {
     MOZ_ASSERT(targetIsWorkerThread,
                "The only PreRun implementation that can fail is "
                "ScriptExecutorRunnable");
     mWorkerPrivate->AssertIsOnWorkerThread();
     MOZ_ASSERT(!JS_IsExceptionPending(mWorkerPrivate->GetJSContext()));
-    // We can't enter a useful compartment on the JSContext here; just pass it
+    // We can't enter a useful realm on the JSContext here; just pass it
     // in as-is.
     PostRun(mWorkerPrivate->GetJSContext(), mWorkerPrivate, false);
     return NS_ERROR_FAILURE;
   }
 
   // Track down the appropriate global, if any, to use for the AutoEntryScript.
   nsCOMPtr<nsIGlobalObject> globalObject;
   bool isMainThread = !targetIsWorkerThread && !mWorkerPrivate->GetParent();
@@ -339,46 +339,46 @@ WorkerRunnable::Run()
   // then we must be a dedicated worker (because there are no
   // Shared/ServiceWorkers whose parent is itself a worker) and then we
   // definitely have a globalObject.  If it _is_ the main thread, globalObject
   // can be null for workers started from JSMs or other non-window contexts,
   // sadly.
   MOZ_ASSERT_IF(!targetIsWorkerThread && !isMainThread,
                 mWorkerPrivate->IsDedicatedWorker() && globalObject);
 
-  // If we're on the parent thread we might be in a null compartment in the
+  // If we're on the parent thread we might be in a null realm in the
   // situation described above when globalObject is null.  Make sure to enter
-  // the compartment of the worker's reflector if there is one.  There might
+  // the realm of the worker's reflector if there is one.  There might
   // not be one if we're just starting to compile the script for this worker.
-  Maybe<JSAutoCompartment> ac;
+  Maybe<JSAutoRealm> ar;
   if (!targetIsWorkerThread &&
       mWorkerPrivate->IsDedicatedWorker() &&
       mWorkerPrivate->ParentEventTargetRef()->GetWrapper()) {
     JSObject* wrapper = mWorkerPrivate->ParentEventTargetRef()->GetWrapper();
 
     // If we're on the parent thread and have a reflector and a globalObject,
-    // then the compartments of cx, globalObject, and the worker's reflector
+    // then the realms of cx, globalObject, and the worker's reflector
     // should all match.
     MOZ_ASSERT_IF(globalObject,
                   js::GetObjectCompartment(wrapper) ==
                     js::GetContextCompartment(cx));
     MOZ_ASSERT_IF(globalObject,
                   js::GetObjectCompartment(wrapper) ==
                     js::GetObjectCompartment(globalObject->GetGlobalJSObject()));
 
     // If we're on the parent thread and have a reflector, then our
-    // JSContext had better be either in the null compartment (and hence
-    // have no globalObject) or in the compartment of our reflector.
+    // JSContext had better be either in the null realm (and hence
+    // have no globalObject) or in the realm of our reflector.
     MOZ_ASSERT(!js::GetContextCompartment(cx) ||
                js::GetObjectCompartment(wrapper) ==
                  js::GetContextCompartment(cx),
                "Must either be in the null compartment or in our reflector "
                "compartment");
 
-    ac.emplace(cx, wrapper);
+    ar.emplace(cx, wrapper);
   }
 
   MOZ_ASSERT(!jsapi->HasException());
   result = WorkerRun(cx, mWorkerPrivate);
   MOZ_ASSERT_IF(result, !jsapi->HasException());
   jsapi->ReportException();
 
   // We can't even assert that this didn't create our global, since in the case
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -1008,25 +1008,25 @@ WorkerDebuggerGlobalScope::CreateSandbox
 void
 WorkerDebuggerGlobalScope::LoadSubScript(JSContext* aCx,
                                          const nsAString& aURL,
                                          const Optional<JS::Handle<JSObject*>>& aSandbox,
                                          ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
-  Maybe<JSAutoCompartment> ac;
+  Maybe<JSAutoRealm> ar;
   if (aSandbox.WasPassed()) {
     JS::Rooted<JSObject*> sandbox(aCx, js::CheckedUnwrap(aSandbox.Value()));
     if (!IsWorkerDebuggerSandbox(sandbox)) {
       aRv.Throw(NS_ERROR_INVALID_ARG);
       return;
     }
 
-    ac.emplace(aCx, sandbox);
+    ar.emplace(aCx, sandbox);
   }
 
   nsTArray<nsString> urls;
   urls.AppendElement(aURL);
   workerinternals::Load(mWorkerPrivate, urls, DebuggerScript, aRv);
 }
 
 void
--- a/dom/worklet/Worklet.cpp
+++ b/dom/worklet/Worklet.cpp
@@ -372,17 +372,17 @@ void
 ExecutionRunnable::RunOnWorkletThread()
 {
   WorkletThread::AssertIsOnWorkletThread();
 
   WorkletThread* workletThread = WorkletThread::Get();
   MOZ_ASSERT(workletThread);
 
   JSContext* cx = workletThread->GetJSContext();
-  JSAutoRequest ar(cx);
+  JSAutoRequest areq(cx);
 
   AutoJSAPI jsapi;
   jsapi.Init();
 
   RefPtr<WorkletGlobalScope> globalScope =
     Worklet::CreateGlobalScope(jsapi.cx(), mWorkletType);
   MOZ_ASSERT(globalScope);
 
@@ -394,17 +394,17 @@ ExecutionRunnable::RunOnWorkletThread()
   NS_ConvertUTF16toUTF8 url(mHandler->URL());
 
   JS::CompileOptions compileOptions(cx);
   compileOptions.setIntroductionType("Worklet");
   compileOptions.setFileAndLine(url.get(), 0);
   compileOptions.setIsRunOnce(true);
   compileOptions.setNoScriptRval(true);
 
-  JSAutoCompartment comp(cx, globalObj);
+  JSAutoRealm ar(cx, globalObj);
 
   JS::SourceBufferHolder buffer(mScriptBuffer.release(), mScriptLength,
                                 JS::SourceBufferHolder::GiveOwnership);
   JS::Rooted<JS::Value> unused(cx);
   if (!JS::Evaluate(cx, compileOptions, buffer, &unused)) {
     ErrorResult error;
     error.MightThrowJSException();
     error.StealExceptionFromJSContext(cx);
@@ -533,17 +533,17 @@ Worklet::CreateGlobalScope(JSContext* aC
     case ePaintWorklet:
       scope = new PaintWorkletGlobalScope();
       break;
   }
 
   JS::Rooted<JSObject*> global(aCx);
   NS_ENSURE_TRUE(scope->WrapGlobalObject(aCx, &global), nullptr);
 
-  JSAutoCompartment ac(aCx, global);
+  JSAutoRealm ar(aCx, global);
 
   // Init Web IDL bindings
   if (!RegisterWorkletBindings(aCx, global)) {
     return nullptr;
   }
 
   JS_FireOnNewGlobalObject(aCx, global);
 
--- a/dom/xbl/nsBindingManager.cpp
+++ b/dom/xbl/nsBindingManager.cpp
@@ -635,17 +635,17 @@ nsBindingManager::GetBindingImplementati
       // binding, some of which may not be exposed on the prototype of
       // untrusted content. We don't need to consider add-on scopes here
       // because they're chrome-only and no Xrays are involved.
       //
       // If there's no separate XBL scope, or if the reflector itself lives in
       // the XBL scope, we'll end up with the global of the reflector.
       JS::Rooted<JSObject*> xblScope(cx, xpc::GetXBLScopeOrGlobal(cx, jsobj));
       NS_ENSURE_TRUE(xblScope, NS_ERROR_UNEXPECTED);
-      JSAutoCompartment ac(cx, xblScope);
+      JSAutoRealm ar(cx, xblScope);
       bool ok = JS_WrapObject(cx, &jsobj);
       NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
       MOZ_ASSERT_IF(js::IsWrapper(jsobj), xpc::IsXrayWrapper(jsobj));
 
       nsresult rv = xpConnect->WrapJSAggregatedToNative(aContent, cx,
                                                         jsobj, aIID, aResult);
       if (NS_FAILED(rv))
         return rv;
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -732,17 +732,17 @@ nsXBLBinding::ChangeDocument(nsIDocument
       if (scriptObject) {
         // XXX Stay in sync! What if a layered binding has an
         // <interface>?!
         // XXXbz what does that comment mean, really?  It seems to date
         // back to when there was such a thing as an <interface>, whever
         // that was...
 
         // Find the right prototype.
-        JSAutoCompartment ac(cx, scriptObject);
+        JSAutoRealm ar(cx, scriptObject);
 
         JS::Rooted<JSObject*> base(cx, scriptObject);
         JS::Rooted<JSObject*> proto(cx);
         for ( ; true; base = proto) { // Will break out on null proto
           if (!JS_GetPrototype(cx, base, &proto)) {
             return;
           }
           if (!proto) {
@@ -890,17 +890,17 @@ GetOrCreateMapEntryForPrototype(JSContex
   // Now, enter the XBL scope, since that's where we need to operate, and wrap
   // the proto accordingly. We hang the map off of the content XBL scope for
   // content, and the Window for chrome (whether add-ons are involved or not).
   JS::Rooted<JSObject*> scope(cx, xpc::GetXBLScopeOrGlobal(cx, proto));
   NS_ENSURE_TRUE(scope, nullptr);
   MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(scope) == scope);
 
   JS::Rooted<JSObject*> wrappedProto(cx, proto);
-  JSAutoCompartment ac(cx, scope);
+  JSAutoRealm ar(cx, scope);
   if (!JS_WrapObject(cx, &wrappedProto)) {
     return nullptr;
   }
 
   // Grab the appropriate WeakMap.
   JS::Rooted<JSObject*> map(cx, GetOrCreateClassObjectMap(cx, scope, name));
   if (!map) {
     return nullptr;
@@ -969,24 +969,24 @@ nsXBLBinding::DoInitJSClass(JSContext *c
 
   // Get the map entry for the parent prototype. In the one-off case that the
   // parent prototype is null, we somewhat hackily just use the WeakMap itself
   // as a property holder.
   JS::Rooted<JSObject*> holder(cx);
   if (parent_proto) {
     holder = GetOrCreateMapEntryForPrototype(cx, parent_proto);
   } else {
-    JSAutoCompartment innerAC(cx, xblScope);
+    JSAutoRealm innerAR(cx, xblScope);
     holder = GetOrCreateClassObjectMap(cx, xblScope, "__ContentClassObjectMap__");
   }
   if (NS_WARN_IF(!holder)) {
     return NS_ERROR_FAILURE;
   }
   js::AssertSameCompartment(holder, xblScope);
-  JSAutoCompartment ac(cx, holder);
+  JSAutoRealm ar(cx, holder);
 
   // Look up the class on the property holder. The only properties on the
   // holder should be class objects. If we don't find the class object, we need
   // to create and define it.
   JS::Rooted<JSObject*> proto(cx);
   JS::Rooted<JS::PropertyDescriptor> desc(cx);
   if (!JS_GetOwnUCPropertyDescriptor(cx, holder, aClassName.get(), &desc)) {
     return NS_ERROR_OUT_OF_MEMORY;
@@ -994,49 +994,49 @@ nsXBLBinding::DoInitJSClass(JSContext *c
   *aNew = !desc.object();
   if (desc.object()) {
     proto = &desc.value().toObject();
     DebugOnly<nsXBLPrototypeBinding*> cachedBinding =
       GetProtoBindingFromClassObject(js::UncheckedUnwrap(proto));
     MOZ_ASSERT(cachedBinding == aProtoBinding);
   } else {
 
-    // We need to create the prototype. First, enter the compartment where it's
+    // We need to create the prototype. First, enter the realm where it's
     // going to live, and create it.
-    JSAutoCompartment ac2(cx, global);
+    JSAutoRealm ar2(cx, global);
     proto = JS_NewObjectWithGivenProto(cx, &gPrototypeJSClass, parent_proto);
     if (!proto) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     // Keep this proto binding alive while we're alive.  Do this first so that
     // we can guarantee that in XBLFinalize this will be non-null.
     // Note that we can't just store aProtoBinding in the private and
     // addref/release the nsXBLDocumentInfo through it, because cycle
     // collection doesn't seem to work right if the private is not an
     // nsISupports.
     nsXBLDocumentInfo* docInfo = aProtoBinding->XBLDocumentInfo();
     ::JS_SetPrivate(proto, docInfo);
     NS_ADDREF(docInfo);
     JS_SetReservedSlot(proto, 0, JS::PrivateValue(aProtoBinding));
 
-    // Next, enter the compartment of the property holder, wrap the proto, and
+    // Next, enter the realm of the property holder, wrap the proto, and
     // stick it on.
-    JSAutoCompartment ac3(cx, holder);
+    JSAutoRealm ar3(cx, holder);
     if (!JS_WrapObject(cx, &proto) ||
         !JS_DefineUCProperty(cx, holder, aClassName.get(), -1, proto,
                              JSPROP_READONLY | JSPROP_PERMANENT))
     {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
-  // Whew. We have the proto. Wrap it back into the compartment of |obj|,
+  // Whew. We have the proto. Wrap it back into the realm of |obj|,
   // splice it in, and return it.
-  JSAutoCompartment ac4(cx, obj);
+  JSAutoRealm ar4(cx, obj);
   if (!JS_WrapObject(cx, &proto) || !JS_SetPrototype(cx, obj, proto)) {
     return NS_ERROR_FAILURE;
   }
   aClassObject.set(proto);
   return NS_OK;
 }
 
 bool
@@ -1105,17 +1105,17 @@ nsXBLBinding::LookupMember(JSContext* aC
     js::GetGlobalForObjectCrossCompartment(mBoundElement->GetWrapper()));
   MOZ_RELEASE_ASSERT(!xpc::IsInContentXBLScope(boundScope));
   JS::Rooted<JSObject*> xblScope(aCx, xpc::GetXBLScope(aCx, boundScope));
   NS_ENSURE_TRUE(xblScope, false);
   MOZ_ASSERT(boundScope != xblScope);
 
   // Enter the xbl scope and invoke the internal version.
   {
-    JSAutoCompartment ac(aCx, xblScope);
+    JSAutoRealm ar(aCx, xblScope);
     JS::Rooted<jsid> id(aCx, aId);
     if (!LookupMemberInternal(aCx, name, id, aDesc, xblScope)) {
       return false;
     }
   }
 
   // Wrap into the caller's scope.
   return JS_WrapPropertyDescriptor(aCx, aDesc);
--- a/dom/xbl/nsXBLProtoImpl.cpp
+++ b/dom/xbl/nsXBLProtoImpl.cpp
@@ -75,24 +75,24 @@ nsXBLProtoImpl::InstallImplementation(ns
 
   // We want to define the canonical set of members in a safe place. If we're
   // using a separate XBL scope, we want to define them there first (so that
   // they'll be available for Xray lookups, among other things), and then copy
   // the properties to the content-side prototype as needed. We don't need to
   // bother about the field accessors here, since we don't use/support those
   // for in-content bindings.
 
-  // First, start by entering the compartment of the XBL scope. This may or may
-  // not be the same compartment as globalObject.
+  // First, start by entering the realm of the XBL scope. This may or may
+  // not be the same realm as globalObject.
   JS::Rooted<JSObject*> globalObject(cx,
     GetGlobalForObjectCrossCompartment(targetClassObject));
   JS::Rooted<JSObject*> scopeObject(cx, xpc::GetXBLScopeOrGlobal(cx, globalObject));
   NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
   MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(scopeObject) == scopeObject);
-  JSAutoCompartment ac(cx, scopeObject);
+  JSAutoRealm ar(cx, scopeObject);
 
   // Determine the appropriate property holder.
   //
   // Note: If |targetIsNew| is false, we'll early-return above. However, that only
   // tells us if the content-side object is new, which may be the case even if
   // we've already set up the binding on the XBL side. For example, if we apply
   // a binding #foo to a <span> when we've already applied it to a <div>, we'll
   // end up with a different content prototype, but we'll already have a property
@@ -159,17 +159,17 @@ nsXBLProtoImpl::InstallImplementation(ns
 
         ok = JS_CopyPropertyFrom(cx, id, targetClassObject, propertyHolder);
         NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
       }
     }
   }
 
   // From here on out, work in the scope of the bound element.
-  JSAutoCompartment ac2(cx, targetClassObject);
+  JSAutoRealm ar2(cx, targetClassObject);
 
   // Install all of our field accessors.
   for (nsXBLProtoImplField* curr = mFields;
        curr;
        curr = curr->GetNext())
     curr->InstallAccessors(cx, targetClassObject);
 
   return NS_OK;
@@ -201,28 +201,28 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLP
   }
 
   // Because our prototype implementation has a class, we need to build up a corresponding
   // class for the concrete implementation in the bound document.
   AutoJSContext cx;
   JS::Rooted<JSObject*> global(cx, sgo->GetGlobalJSObject());
   JS::Rooted<JS::Value> v(cx);
 
-  JSAutoCompartment ac(cx, global);
+  JSAutoRealm ar(cx, global);
   // Make sure the interface object is created before the prototype object
   // so that XULElement is hidden from content. See bug 909340.
   bool defineOnGlobal = dom::XULElementBinding::ConstructorEnabled(cx, global);
   dom::XULElementBinding::GetConstructorObjectHandle(cx, defineOnGlobal);
 
   rv = nsContentUtils::WrapNative(cx, aBoundElement, &v,
                                   /* aAllowWrapping = */ false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   JS::Rooted<JSObject*> value(cx, &v.toObject());
-  JSAutoCompartment ac2(cx, value);
+  JSAutoRealm ar2(cx, value);
 
   // All of the above code was just obtaining the bound element's script object and its immediate
   // concrete base class.  We need to alter the object so that our concrete class is interposed
   // between the object and its base class.  We become the new base class of the object, and the
   // object's old base class becomes the new class' base class.
   rv = aBinding->InitClass(mClassName, cx, value, aTargetClassObject, aTargetIsNew);
   if (NS_FAILED(rv)) {
     return rv;
--- a/dom/xbl/nsXBLProtoImplField.cpp
+++ b/dom/xbl/nsXBLProtoImplField.cpp
@@ -170,40 +170,40 @@ InstallXBLField(JSContext* cx,
     xpc::Throw(cx, NS_ERROR_UNEXPECTED);
     return false;
   }
 
   // Now that |this| is okay, actually install the field.
 
   // Because of the possibility (due to XBL binding inheritance, because each
   // XBL binding lives in its own global object) that |this| might be in a
-  // different compartment from the callee (not to mention that this method can
+  // different realm from the callee (not to mention that this method can
   // be called with an arbitrary |this| regardless of how insane XBL is), and
-  // because in this method we've entered |this|'s compartment (see in
-  // Field[GS]etter where we attempt a cross-compartment call), we must enter
-  // the callee's compartment to access its reserved slots.
+  // because in this method we've entered |this|'s realm (see in
+  // Field[GS]etter where we attempt a cross-realm call), we must enter
+  // the callee's realm to access its reserved slots.
   nsXBLPrototypeBinding* protoBinding;
   nsAutoJSString fieldName;
   {
-    JSAutoCompartment ac(cx, callee);
+    JSAutoRealm ar(cx, callee);
 
     JS::Rooted<JSObject*> xblProto(cx);
     xblProto = &js::GetFunctionNativeReserved(callee, XBLPROTO_SLOT).toObject();
 
     JS::Rooted<JS::Value> name(cx, js::GetFunctionNativeReserved(callee, FIELD_SLOT));
     if (!fieldName.init(cx, name.toString())) {
       return false;
     }
 
     MOZ_ALWAYS_TRUE(JS_ValueToId(cx, name, idp));
 
-    // If a separate XBL scope is being used, the callee is not same-compartment
+    // If a separate XBL scope is being used, the callee is not same-realm
     // with the xbl prototype, and the object is a cross-compartment wrapper.
     xblProto = js::UncheckedUnwrap(xblProto);
-    JSAutoCompartment ac2(cx, xblProto);
+    JSAutoRealm ar2(cx, xblProto);
     JS::Value slotVal = ::JS_GetReservedSlot(xblProto, 0);
     protoBinding = static_cast<nsXBLPrototypeBinding*>(slotVal.toPrivate());
     MOZ_ASSERT(protoBinding);
   }
 
   nsXBLProtoImplField* field = protoBinding->FindField(fieldName);
   MOZ_ASSERT(field);
 
@@ -221,17 +221,17 @@ InstallXBLField(JSContext* cx,
 bool
 FieldGetterImpl(JSContext *cx, const JS::CallArgs& args)
 {
   JS::Handle<JS::Value> thisv = args.thisv();
   MOZ_ASSERT(ValueHasISupportsPrivate(thisv));
 
   JS::Rooted<JSObject*> thisObj(cx, &thisv.toObject());
 
-  // We should be in the compartment of |this|. If we got here via nativeCall,
+  // We should be in the realm of |this|. If we got here via nativeCall,
   // |this| is not same-compartment with |callee|, and it's possible via
   // asymmetric security semantics that |args.calleev()| is actually a security
   // wrapper. In this case, we know we want to do an unsafe unwrap, and
   // InstallXBLField knows how to handle cross-compartment pointers.
   bool installed = false;
   JS::Rooted<JSObject*> callee(cx, js::UncheckedUnwrap(&args.calleev().toObject()));
   JS::Rooted<jsid> id(cx);
   if (!InstallXBLField(cx, callee, thisObj, &id, &installed)) {
@@ -257,17 +257,17 @@ FieldGetter(JSContext *cx, unsigned argc
 bool
 FieldSetterImpl(JSContext *cx, const JS::CallArgs& args)
 {
   JS::Handle<JS::Value> thisv = args.thisv();
   MOZ_ASSERT(ValueHasISupportsPrivate(thisv));
 
   JS::Rooted<JSObject*> thisObj(cx, &thisv.toObject());
 
-  // We should be in the compartment of |this|. If we got here via nativeCall,
+  // We should be in the realm of |this|. If we got here via nativeCall,
   // |this| is not same-compartment with |callee|, and it's possible via
   // asymmetric security semantics that |args.calleev()| is actually a security
   // wrapper. In this case, we know we want to do an unsafe unwrap, and
   // InstallXBLField knows how to handle cross-compartment pointers.
   bool installed = false;
   JS::Rooted<JSObject*> callee(cx, js::UncheckedUnwrap(&args.calleev().toObject()));
   JS::Rooted<jsid> id(cx);
   if (!InstallXBLField(cx, callee, thisObj, &id, &installed)) {
@@ -323,17 +323,17 @@ nsXBLProtoImplField::InstallAccessors(JS
     return NS_ERROR_FAILURE;
   if (found)
     return NS_OK;
 
   // FieldGetter and FieldSetter need to run in the XBL scope so that they can
   // see through any SOWs on their targets.
 
   // First, enter the XBL scope, and compile the functions there.
-  JSAutoCompartment ac(aCx, scopeObject);
+  JSAutoRealm ar(aCx, scopeObject);
   JS::Rooted<JS::Value> wrappedClassObj(aCx, JS::ObjectValue(*aTargetClassObject));
   if (!JS_WrapValue(aCx, &wrappedClassObj))
     return NS_ERROR_OUT_OF_MEMORY;
 
   JS::Rooted<JSObject*> get(aCx,
     JS_GetFunctionObject(js::NewFunctionByIdWithReserved(aCx, FieldGetter,
                                                          0, 0, id)));
   if (!get) {
@@ -350,17 +350,17 @@ nsXBLProtoImplField::InstallAccessors(JS
     return NS_ERROR_OUT_OF_MEMORY;
   }
   js::SetFunctionNativeReserved(set, XBLPROTO_SLOT, wrappedClassObj);
   js::SetFunctionNativeReserved(set, FIELD_SLOT,
                                 JS::StringValue(JSID_TO_STRING(id)));
 
   // Now, re-enter the class object's scope, wrap the getters/setters, and define
   // them there.
-  JSAutoCompartment ac2(aCx, aTargetClassObject);
+  JSAutoRealm ar2(aCx, aTargetClassObject);
   if (!JS_WrapObject(aCx, &get) || !JS_WrapObject(aCx, &set)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   if (!::JS_DefinePropertyById(aCx, aTargetClassObject, id,
                                JS_DATA_TO_FUNC_PTR(JSNative, get.get()),
                                JS_DATA_TO_FUNC_PTR(JSNative, set.get()),
                                AccessorAttributes())) {
@@ -396,17 +396,17 @@ nsXBLProtoImplField::InstallField(JS::Ha
   nsIGlobalObject* globalObject = xpc::WindowGlobalOrNull(aBoundNode);
   if (!globalObject) {
     return NS_OK;
   }
 
   // We are going to run script via EvaluateString, so we need a script entry
   // point, but as this is XBL related it does not appear in the HTML spec.
   // We need an actual JSContext to do GetXBLScopeOrGlobal, and it needs to
-  // be in the compartment of globalObject.  But we want our XBL execution scope
+  // be in the realm of globalObject.  But we want our XBL execution scope
   // to be our entry global.
   AutoJSAPI jsapi;
   if (!jsapi.Init(globalObject)) {
     return NS_ERROR_UNEXPECTED;
   }
   MOZ_ASSERT(!::JS_IsExceptionPending(jsapi.cx()),
              "Shouldn't get here when an exception is pending!");
 
@@ -445,23 +445,23 @@ nsXBLProtoImplField::InstallField(JS::Ha
 
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW) {
     // Report the exception now, before we try using the JSContext for
     // the JS_DefineUCProperty call.  Note that this reports in our current
-    // compartment, which is the XBL scope.
+    // realm, which is the XBL scope.
     aes.ReportException();
   }
 
-  // Now, enter the node's compartment, wrap the eval result, and define it on
+  // Now, enter the node's realm, wrap the eval result, and define it on
   // the bound node.
-  JSAutoCompartment ac2(cx, aBoundNode);
+  JSAutoRealm ar2(cx, aBoundNode);
   nsDependentString name(mName);
   if (!JS_WrapValue(cx, &result) ||
       !::JS_DefineUCProperty(cx, aBoundNode,
                              reinterpret_cast<const char16_t*>(mName),
                              name.Length(), result, mJSAttributes)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
--- a/dom/xbl/nsXBLProtoImplMethod.cpp
+++ b/dom/xbl/nsXBLProtoImplMethod.cpp
@@ -183,17 +183,17 @@ nsXBLProtoImplMethod::CompileMember(Auto
   NS_ConvertUTF16toUTF8 cname(mName);
   NS_ConvertUTF16toUTF8 functionUri(aClassStr);
   int32_t hash = functionUri.RFindChar('#');
   if (hash != kNotFound) {
     functionUri.Truncate(hash);
   }
 
   JSContext *cx = jsapi.cx();
-  JSAutoCompartment ac(cx, aClassObject);
+  JSAutoRealm ar(cx, aClassObject);
   JS::CompileOptions options(cx);
   options.setFileAndLine(functionUri.get(),
                          uncompiledMethod->mBodyText.GetLineNumber());
   JS::Rooted<JSObject*> methodObject(cx);
   JS::AutoObjectVector emptyVector(cx);
   nsresult rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options, cname,
                                            paramCount,
                                            const_cast<const char**>(args),
--- a/dom/xbl/nsXBLProtoImplProperty.cpp
+++ b/dom/xbl/nsXBLProtoImplProperty.cpp
@@ -184,17 +184,17 @@ nsXBLProtoImplProperty::CompileMember(Au
     }
   }
 
   bool deletedGetter = false;
   nsXBLTextWithLineNumber *getterText = mGetter.GetUncompiled();
   if (getterText && getterText->GetText()) {
     nsDependentString getter(getterText->GetText());
     if (!getter.IsEmpty()) {
-      JSAutoCompartment ac(cx, aClassObject);
+      JSAutoRealm ar(cx, aClassObject);
       JS::CompileOptions options(cx);
       options.setFileAndLine(functionUri.get(), getterText->GetLineNumber());
       nsCString name = NS_LITERAL_CSTRING("get_") + NS_ConvertUTF16toUTF8(mName);
       JS::Rooted<JSObject*> getterObject(cx);
       JS::AutoObjectVector emptyVector(cx);
       rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options, name, 0,
                                       nullptr, getter, getterObject.address());
 
@@ -229,17 +229,17 @@ nsXBLProtoImplProperty::CompileMember(Au
     return rv;
   }
 
   bool deletedSetter = false;
   nsXBLTextWithLineNumber *setterText = mSetter.GetUncompiled();
   if (setterText && setterText->GetText()) {
     nsDependentString setter(setterText->GetText());
     if (!setter.IsEmpty()) {
-      JSAutoCompartment ac(cx, aClassObject);
+      JSAutoRealm ar(cx, aClassObject);
       JS::CompileOptions options(cx);
       options.setFileAndLine(functionUri.get(), setterText->GetLineNumber());
       nsCString name = NS_LITERAL_CSTRING("set_") + NS_ConvertUTF16toUTF8(mName);
       JS::Rooted<JSObject*> setterObject(cx);
       JS::AutoObjectVector emptyVector(cx);
       rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options, name, 1,
                                       gPropertyArgs, setter,
                                       setterObject.address());
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -349,17 +349,17 @@ nsXBLPrototypeHandler::ExecuteHandler(Ev
   NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
 
   // Bind it to the bound element. Note that if we're using a separate XBL scope,
   // we'll actually be binding the event handler to a cross-compartment wrapper
   // to the bound element's reflector.
 
   // First, enter our XBL scope. This is where the generic handler should have
   // been compiled, above.
-  JSAutoCompartment ac(cx, scopeObject);
+  JSAutoRealm ar(cx, scopeObject);
   JS::Rooted<JSObject*> genericHandler(cx, handler.get());
   bool ok = JS_WrapObject(cx, &genericHandler);
   NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
   MOZ_ASSERT(!js::IsCrossCompartmentWrapper(genericHandler));
 
   // Build a scope chain in the XBL scope.
   RefPtr<Element> targetElement = do_QueryObject(scriptTarget);
   JS::AutoObjectVector scopeChain(cx);
@@ -420,32 +420,32 @@ nsXBLPrototypeHandler::EnsureEventHandle
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint32_t argCount;
   const char **argNames;
   nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, false, &argCount,
                                    &argNames);
 
   // Compile the event handler in the xbl scope.
-  JSAutoCompartment ac(cx, scopeObject);
+  JSAutoRealm ar(cx, scopeObject);
   JS::CompileOptions options(cx);
   options.setFileAndLine(bindingURI.get(), mLineNumber);
 
   JS::Rooted<JSObject*> handlerFun(cx);
   JS::AutoObjectVector emptyVector(cx);
   rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options,
                                   nsAtomCString(aName), argCount,
                                   argNames, handlerText,
                                   handlerFun.address());
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(handlerFun, NS_ERROR_FAILURE);
 
   // Wrap the handler into the content scope, since we're about to stash it
   // on the DOM window and such.
-  JSAutoCompartment ac2(cx, globalObject);
+  JSAutoRealm ar2(cx, globalObject);
   bool ok = JS_WrapObject(cx, &handlerFun);
   NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
   aHandler.set(handlerFun);
   NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
 
   if (pWindow) {
     pWindow->CacheXBLPrototypeHandler(this, aHandler);
   }
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -3227,17 +3227,17 @@ XULDocument::ExecuteScript(nsXULPrototyp
 
     JS::Rooted<JSScript*> scriptObject(cx, aScript->GetScriptObject());
     NS_ENSURE_TRUE(scriptObject, NS_ERROR_UNEXPECTED);
 
     JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
     NS_ENSURE_TRUE(xpc::Scriptability::Get(global).Allowed(), NS_OK);
 
     JS::ExposeObjectToActiveJS(global);
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     // The script is in the compilation scope. Clone it into the target scope
     // and execute it. On failure, ~AutoScriptEntry will handle exceptions, so
     // there is no need to manually check the return value.
     JS::RootedValue rval(cx);
     JS::CloneAndExecuteScript(cx, scriptObject, &rval);
 
     return NS_OK;
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -382,17 +382,17 @@ XPCShellEnvironment::~XPCShellEnvironmen
         AutoJSAPI jsapi;
         if (!jsapi.Init(GetGlobalObject())) {
             return;
         }
         JSContext* cx = jsapi.cx();
         Rooted<JSObject*> global(cx, GetGlobalObject());
 
         {
-            JSAutoCompartment ac(cx, global);
+            JSAutoRealm ar(cx, global);
             JS_SetAllNonReservedSlotsToUndefined(cx, global);
         }
         mGlobalHolder.reset();
 
         JS_GC(cx);
     }
 }
 
@@ -443,17 +443,17 @@ XPCShellEnvironment::Init()
         NS_ERROR("InitClassesWithNewWrappedGlobal failed!");
         return false;
     }
 
     if (!globalObj) {
         NS_ERROR("Failed to get global JSObject!");
         return false;
     }
-    JSAutoCompartment ac(cx, globalObj);
+    JSAutoRealm ar(cx, globalObj);
 
     backstagePass->SetGlobalObject(globalObj);
 
     JS::Rooted<Value> privateVal(cx, PrivateValue(this));
     if (!JS_DefineProperty(cx, globalObj, "__XPCShellEnvironment",
                            privateVal,
                            JSPROP_READONLY | JSPROP_PERMANENT) ||
         !JS_DefineFunctions(cx, globalObj, gGlobalFunctions) ||
--- a/js/ductwork/debugger/JSDebugger.cpp
+++ b/js/ductwork/debugger/JSDebugger.cpp
@@ -45,17 +45,17 @@ JSDebugger::AddClass(JS::Handle<JS::Valu
   }
 
   JS::RootedObject obj(cx, &global.toObject());
   obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
   if (!obj) {
     return NS_ERROR_FAILURE;
   }
 
-  JSAutoCompartment ac(cx, obj);
+  JSAutoRealm ar(cx, obj);
   if (JS_GetGlobalForObject(cx, obj) != obj) {
     return NS_ERROR_INVALID_ARG;
   }
 
   if (!JS_DefineDebuggerObject(cx, obj)) {
     return NS_ERROR_FAILURE;
   }
 
--- a/js/ipc/JavaScriptLogging.h
+++ b/js/ipc/JavaScriptLogging.h
@@ -101,17 +101,17 @@ class Logging
         const char* side;
         const char* objDesc;
         void* ptr;
 
         if (local == incoming) {
             JS::RootedObject obj(cx);
             obj = shared->objects_.find(id);
             if (obj) {
-                JSAutoCompartment ac(cx, obj);
+                JSAutoRealm ar(cx, obj);
                 objDesc = js::ObjectClassName(cx, obj);
             } else {
                 objDesc = "<dead object>";
             }
 
             side = shared->isParent() ? "parent" : "child";
             ptr = js::UncheckedUnwrap(obj, true);
         } else {
--- a/js/ipc/JavaScriptParent.cpp
+++ b/js/ipc/JavaScriptParent.cpp
@@ -68,17 +68,17 @@ JavaScriptParent::allowMessage(JSContext
 
     MessageChannel* channel = GetIPCChannel();
     bool isSafe = channel->IsInTransaction();
 
     bool warn = !isSafe;
     nsIGlobalObject* global = dom::GetIncumbentGlobal();
     JS::Rooted<JSObject*> jsGlobal(cx, global ? global->GetGlobalJSObject() : nullptr);
     if (jsGlobal) {
-        JSAutoCompartment ac(cx, jsGlobal);
+        JSAutoRealm ar(cx, jsGlobal);
 
         if (!xpc::CompartmentPrivate::Get(jsGlobal)->allowCPOWs) {
             if (ForbidUnsafeBrowserCPOWs() && !isSafe) {
                 Telemetry::Accumulate(Telemetry::BROWSER_SHIM_USAGE_BLOCKED, 1);
                 JS_ReportErrorASCII(cx, "unsafe CPOW usage forbidden");
                 return false;
             }
         }
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -531,20 +531,20 @@ JavaScriptShared::findObjectById(JSConte
         JS_ReportErrorASCII(cx, "operation not possible on dead CPOW");
         return nullptr;
     }
 
     // Each process has a dedicated compartment for CPOW targets. All CPOWs
     // from the other process point to objects in this scope. From there, they
     // can access objects in other compartments using cross-compartment
     // wrappers.
-    JSAutoCompartment ac(cx, scopeForTargetObjects());
+    JSAutoRealm ar(cx, scopeForTargetObjects());
     if (objId.hasXrayWaiver()) {
         {
-            JSAutoCompartment ac2(cx, obj);
+            JSAutoRealm ar2(cx, obj);
             obj = js::ToWindowProxyIfWindow(obj);
             MOZ_ASSERT(obj);
         }
         if (!xpc::WrapperFactory::WaiveXrayAndWrap(cx, &obj))
             return nullptr;
     } else {
         if (!JS_WrapObject(cx, &obj))
             return nullptr;
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -1182,17 +1182,17 @@ JSObject*
 WrapperOwner::fromRemoteObjectVariant(JSContext* cx, const RemoteObject& objVar)
 {
     ObjectId objId = ObjectId::deserialize(objVar.serializedId());
     RootedObject obj(cx, findCPOWById(objId));
     if (!obj) {
 
         // All CPOWs live in the privileged junk scope.
         RootedObject junkScope(cx, xpc::PrivilegedJunkScope());
-        JSAutoCompartment ac(cx, junkScope);
+        JSAutoRealm ar(cx, junkScope);
         RootedValue v(cx, UndefinedValue());
         // We need to setLazyProto for the getPrototype/getPrototypeIfOrdinary
         // hooks.
         ProxyOptions options;
         options.setLazyProto(true);
         obj = NewProxyObject(cx,
                              &CPOWProxyHandler::singleton,
                              v,
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -833,17 +833,17 @@ static const uint32_t JSCLASS_FOREGROUND
 // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
 // previously allowed, but is now an ES5 violation and thus unsupported.
 //
 // JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at
 // the beginning of every global object's slots for use by the
 // application.
 static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
 static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT =
-    JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 37;
+    JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 36;
 
 #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                              \
     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
 #define JSCLASS_GLOBAL_FLAGS                                                  \
     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
 #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
--- a/js/rust/build.rs
+++ b/js/rust/build.rs
@@ -157,17 +157,17 @@ const WHITELIST_TYPES: &'static [&'stati
     "JS::Handle",
     "JS::HandleFunction",
     "JS::HandleId",
     "JS::HandleObject",
     "JS::HandleString",
     "JS::HandleValue",
     "JS::HandleValueArray",
     "JS::IsAcceptableThis",
-    "JSAutoCompartment",
+    "JSAutoRealm",
     "JSAutoStructuredCloneBuffer",
     "JSClass",
     "JSClassOps",
     "JSContext",
     "JSErrNum",
     "JSErrorCallback",
     "JSErrorFormatString",
     "JSErrorReport",
--- a/js/rust/src/ac.rs
+++ b/js/rust/src/ac.rs
@@ -1,56 +1,56 @@
 use jsapi::root::*;
 #[cfg(feature = "debugmozjs")]
 use std::ptr;
 
 #[derive(Debug)]
-pub struct AutoCompartment(JSAutoCompartment);
+pub struct AutoCompartment(JSAutoRealm);
 
 impl AutoCompartment {
     #[cfg(feature = "debugmozjs")]
     pub unsafe fn with_obj(cx: *mut JSContext,
                            target: *mut JSObject)
                            -> AutoCompartment
     {
         let mut notifier = mozilla::detail::GuardObjectNotifier {
             mStatementDone: ptr::null_mut(),
         };
 
         AutoCompartment(
-            JSAutoCompartment::new(
+            JSAutoRealm::new(
                 cx,
                 target,
                 &mut notifier as *mut _))
     }
 
     #[cfg(not(feature = "debugmozjs"))]
     pub unsafe fn with_obj(cx: *mut JSContext,
                            target: *mut JSObject)
                            -> AutoCompartment
     {
-        AutoCompartment(JSAutoCompartment::new(cx, target))
+        AutoCompartment(JSAutoRealm::new(cx, target))
     }
 
     #[cfg(feature = "debugmozjs")]
     pub unsafe fn with_script(cx: *mut JSContext,
                               target: *mut JSScript)
                               -> AutoCompartment
     {
         let mut notifier = mozilla::detail::GuardObjectNotifier {
             mStatementDone: ptr::null_mut(),
         };
 
         AutoCompartment(
-            JSAutoCompartment::new1(
+            JSAutoRealm::new1(
                 cx,
                 target,
                 &mut notifier as *mut _))
     }
 
     #[cfg(not(feature = "debugmozjs"))]
     pub unsafe fn with_script(cx: *mut JSContext,
                               target: *mut JSScript)
                               -> AutoCompartment
     {
-        AutoCompartment(JSAutoCompartment::new1(cx, target))
+        AutoCompartment(JSAutoRealm::new1(cx, target))
     }
 }
--- a/js/rust/src/rust.rs
+++ b/js/rust/src/rust.rs
@@ -604,17 +604,17 @@ impl GCMethods for JS::Value {
     unsafe fn post_barrier(v: *mut JS::Value, prev: JS::Value, next: JS::Value) {
         JS::HeapValuePostBarrier(v, &prev, &next);
     }
 }
 
 // ___________________________________________________________________________
 // Implementations for various things in jsapi.rs
 
-impl Drop for JSAutoCompartment {
+impl Drop for JSAutoRealm {
     fn drop(&mut self) {
         unsafe { JS_LeaveCompartment(self.cx_, self.oldCompartment_); }
     }
 }
 
 impl JSJitMethodCallArgs {
     #[inline]
     pub fn get(&self, i: u32) -> JS::HandleValue {
--- a/js/src/builtin/DataViewObject.cpp
+++ b/js/src/builtin/DataViewObject.cpp
@@ -229,17 +229,17 @@ DataViewObject::constructWrapped(JSConte
     if (!proto) {
         proto = GlobalObject::getOrCreateDataViewPrototype(cx, global);
         if (!proto)
             return false;
     }
 
     RootedObject dv(cx);
     {
-        JSAutoCompartment ac(cx, unwrapped);
+        JSAutoRealm ar(cx, unwrapped);
 
         Rooted<ArrayBufferObjectMaybeShared*> buffer(cx);
         buffer = &unwrapped->as<ArrayBufferObjectMaybeShared>();
 
         RootedObject wrappedProto(cx, proto);
         if (!cx->compartment()->wrap(cx, &wrappedProto))
             return false;
 
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1689,34 +1689,34 @@ CallObjFunc(RetT(*ObjFunc)(JSContext*, H
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     // Always unwrap, in case this is an xray or cross-compartment wrapper.
     RootedObject unwrappedObj(cx);
     unwrappedObj = UncheckedUnwrap(obj);
 
-    // Enter the compartment of the backing object before calling functions on
+    // Enter the realm of the backing object before calling functions on
     // it.
-    JSAutoCompartment ac(cx, unwrappedObj);
+    JSAutoRealm ar(cx, unwrappedObj);
     return ObjFunc(cx, unwrappedObj);
 }
 
 // Handles Has/Delete for public jsapi map/set access
 bool
 CallObjFunc(bool(*ObjFunc)(JSContext *cx, HandleObject obj, HandleValue key, bool *rval),
             JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, key);
 
     // Always unwrap, in case this is an xray or cross-compartment wrapper.
     RootedObject unwrappedObj(cx);
     unwrappedObj = UncheckedUnwrap(obj);
-    JSAutoCompartment ac(cx, unwrappedObj);
+    JSAutoRealm ar(cx, unwrappedObj);
 
     // If we're working with a wrapped map/set, rewrap the key into the
     // compartment of the unwrapped map/set.
     RootedValue wrappedKey(cx, key);
     if (obj != unwrappedObj) {
         if (!JS_WrapValue(cx, &wrappedKey))
             return false;
     }
@@ -1734,17 +1734,17 @@ CallObjFunc(bool(*ObjFunc)(JSContext* cx
     assertSameCompartment(cx, obj);
 
     // Always unwrap, in case this is an xray or cross-compartment wrapper.
     RootedObject unwrappedObj(cx);
     unwrappedObj = UncheckedUnwrap(obj);
     {
         // Retrieve the iterator while in the unwrapped map/set's compartment,
         // otherwise we'll crash on a compartment assert.
-        JSAutoCompartment ac(cx, unwrappedObj);
+        JSAutoRealm ar(cx, unwrappedObj);
         if (!ObjFunc(cx, iterType, unwrappedObj, rval))
             return false;
     }
 
     // If the caller is in a different compartment than the map/set, rewrap the
     // iterator object into the caller's compartment.
     if (obj != unwrappedObj) {
         if (!JS_WrapValue(cx, rval))
@@ -1768,22 +1768,22 @@ JS::MapSize(JSContext* cx, HandleObject 
 }
 
 JS_PUBLIC_API(bool)
 JS::MapGet(JSContext* cx, HandleObject obj, HandleValue key, MutableHandleValue rval)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, key, rval);
 
-    // Unwrap the object, and enter its compartment. If object isn't wrapped,
+    // Unwrap the object, and enter its realm. If object isn't wrapped,
     // this is essentially a noop.
     RootedObject unwrappedObj(cx);
     unwrappedObj = UncheckedUnwrap(obj);
     {
-        JSAutoCompartment ac(cx, unwrappedObj);
+        JSAutoRealm ar(cx, unwrappedObj);
         RootedValue wrappedKey(cx, key);
 
         // If we passed in a wrapper, wrap our key into its compartment now.
         if (obj != unwrappedObj) {
             if (!JS_WrapValue(cx, &wrappedKey))
                 return false;
         }
         if (!MapObject::get(cx, unwrappedObj, wrappedKey, rval))
@@ -1804,17 +1804,17 @@ JS::MapSet(JSContext *cx, HandleObject o
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, key, val);
 
     // Unwrap the object, and enter its compartment. If object isn't wrapped,
     // this is essentially a noop.
     RootedObject unwrappedObj(cx);
     unwrappedObj = UncheckedUnwrap(obj);
     {
-        JSAutoCompartment ac(cx, unwrappedObj);
+        JSAutoRealm ar(cx, unwrappedObj);
 
         // If we passed in a wrapper, wrap both key and value before adding to
         // the map
         RootedValue wrappedKey(cx, key);
         RootedValue wrappedValue(cx, val);
         if (obj != unwrappedObj) {
             if (!JS_WrapValue(cx, &wrappedKey) ||
                 !JS_WrapValue(cx, &wrappedValue)) {
@@ -1885,17 +1885,17 @@ JS::SetAdd(JSContext *cx, HandleObject o
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, key);
 
     // Unwrap the object, and enter its compartment. If object isn't wrapped,
     // this is essentially a noop.
     RootedObject unwrappedObj(cx);
     unwrappedObj = UncheckedUnwrap(obj);
     {
-        JSAutoCompartment ac(cx, unwrappedObj);
+        JSAutoRealm ar(cx, unwrappedObj);
 
         // If we passed in a wrapper, wrap key before adding to the set
         RootedValue wrappedKey(cx, key);
         if (obj != unwrappedObj) {
             if (!JS_WrapValue(cx, &wrappedKey))
                 return false;
         }
         return SetObject::add(cx, unwrappedObj, wrappedKey);
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -1966,17 +1966,17 @@ PerformPromiseAll(JSContext *cx, JS::For
     // should be OK because the only things we hand the
     // PromiseAllResolveElement function to are the "then" calls we do and in
     // the case when the Promise's compartment is not the current compartment
     // those are happening over Xrays anyway, which means they get the
     // canonical "then" function and content can't see our
     // PromiseAllResolveElement.
     RootedObject valuesArray(cx);
     if (unwrappedPromiseObj) {
-        JSAutoCompartment ac(cx, unwrappedPromiseObj);
+        JSAutoRealm ar(cx, unwrappedPromiseObj);
         valuesArray = NewDenseFullyAllocatedArray(cx, 0);
     } else {
         valuesArray = NewDenseFullyAllocatedArray(cx, 0);
     }
     if (!valuesArray)
         return false;
 
     RootedValue valuesArrayVal(cx, ObjectValue(*valuesArray));
@@ -2025,20 +2025,20 @@ PerformPromiseAll(JSContext *cx, JS::For
                                              promiseObj);
             }
 
             // We're all set for now!
             return true;
         }
 
         // Step h.
-        { // Scope for the JSAutoCompartment we need to work with valuesArray.  We
+        { // Scope for the JSAutoRealm we need to work with valuesArray.  We
             // mostly do this for performance; we could go ahead and do the define via
             // a cross-compartment proxy instead...
-            JSAutoCompartment ac(cx, valuesArray);
+            JSAutoRealm ar(cx, valuesArray);
             indexId = INT_TO_JSID(index);
             if (!DefineDataProperty(cx, valuesArray, indexId, UndefinedHandleValue))
                 return false;
         }
 
         // Step i.
         // Sadly, because someone could have overridden
         // "resolve" on the canonical Promise constructor.
--- a/js/src/devtools/rootAnalysis/annotations.js
+++ b/js/src/devtools/rootAnalysis/annotations.js
@@ -196,17 +196,17 @@ var ignoreFunctions = {
     "NS_LogCOMPtrRelease": true,
 
     // FIXME!
     "NS_DebugBreak": true,
 
     // These are a little overzealous -- these destructors *can* GC if they end
     // up wrapping a pending exception. See bug 898815 for the heavyweight fix.
     "void js::AutoCompartment::~AutoCompartment(int32)" : true,
-    "void JSAutoCompartment::~JSAutoCompartment(int32)" : true,
+    "void JSAutoRealm::~JSAutoRealm(int32)" : true,
 
     // Similar to heap snapshot mock classes, and GTests below. This posts a
     // synchronous runnable when a GTest fails, and we are pretty sure that the
     // particular runnable it posts can't even GC, but the analysis isn't
     // currently smart enough to determine that. In either case, this is (a)
     // only in GTests, and (b) only when the Gtest has already failed. We have
     // static and dynamic checks for no GC in the non-test code, and in the test
     // code we fall back to only the dynamic checks.
--- a/js/src/fuzz-tests/tests.cpp
+++ b/js/src/fuzz-tests/tests.cpp
@@ -48,17 +48,17 @@ jsfuzz_createGlobal(JSContext* cx, JSPri
 #ifdef ENABLE_STREAMS
     options.creationOptions().setStreamsEnabled(true);
 #endif
     newGlobal = JS_NewGlobalObject(cx, getGlobalClass(), principals, JS::FireOnNewGlobalHook,
                                    options);
     if (!newGlobal)
         return nullptr;
 
-    JSAutoCompartment ac(cx, newGlobal);
+    JSAutoRealm ar(cx, newGlobal);
 
     // Populate the global object with the standard globals like Object and
     // Array.
     if (!JS_InitStandardClasses(cx, newGlobal))
         return nullptr;
 
     return newGlobal;
 }
--- a/js/src/gdb/gdb-tests.cpp
+++ b/js/src/gdb/gdb-tests.cpp
@@ -77,23 +77,23 @@ main(int argc, const char** argv)
     JSContext* cx = checkPtr(JS_NewContext(1024 * 1024));
 
     JS_SetGCParameter(cx, JSGC_MAX_BYTES, 0xffffffff);
     JS_SetNativeStackQuota(cx, 5000000);
 
     checkBool(JS::InitSelfHostedCode(cx));
     JS::SetWarningReporter(cx, reportWarning);
 
-    JSAutoRequest ar(cx);
+    JSAutoRequest areq(cx);
 
     /* Create the global object. */
     JS::CompartmentOptions options;
     RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class,
                         nullptr, JS::FireOnNewGlobalHook, options)));
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     /* Populate the global object with the standard globals,
        like Object and Array. */
     checkBool(JS_InitStandardClasses(cx, global));
 
     argv++;
     while (*argv) {
         const char* name = *argv++;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1461027.js
@@ -0,0 +1,4 @@
+for (var i = 0; i < 99; i++) {
+	    w = new TypedObject.ArrayType(TypedObject.int32, 100).build(function() {});
+}
+relazifyFunctions();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1461319.js
@@ -0,0 +1,7 @@
+// |jit-test| error: InternalError
+gczeal(14);
+var g = newGlobal();
+g.eval('function f(a) { evaluate("f(" + " - 1);", {newContext: true}); }');
+var dbg = new Debugger(g);
+dbg.onEnterFrame = function(frame) {};
+g.f();
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -329,16 +329,21 @@ class MacroAssembler : public MacroAssem
     explicit MacroAssembler(JSContext* cx);
 
     // wasm compilation handles its own JitContext-pushing
     struct WasmToken {};
     explicit MacroAssembler(WasmToken, TempAllocator& alloc);
 
   public:
     MoveResolver& moveResolver() {
+        // As an optimization, the MoveResolver is a persistent data structure
+        // shared between visitors in the CodeGenerator. This assertion
+        // checks that state is not leaking from visitor to visitor
+        // via an unresolved addMove().
+        MOZ_ASSERT(moveResolver_.hasNoPendingMoves());
         return moveResolver_;
     }
 
     size_t instructionsSize() const {
         return size();
     }
 
 #ifdef JS_HAS_HIDDEN_SP
--- a/js/src/jit/MoveResolver.cpp
+++ b/js/src/jit/MoveResolver.cpp
@@ -2,16 +2,17 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/MoveResolver.h"
 
 #include "mozilla/Attributes.h"
+#include "mozilla/ScopeExit.h"
 
 #include "jit/MacroAssembler.h"
 #include "jit/RegisterSets.h"
 
 using namespace js;
 using namespace js::jit;
 
 MoveOperand::MoveOperand(MacroAssembler& masm, const ABIArg& arg)
@@ -173,22 +174,28 @@ SplitIntoUpperHalf(const MoveOperand& mo
         return MoveOperand(upperSingle);
     }
 
     MOZ_ASSERT(move.isMemoryOrEffectiveAddress());
     return MoveOperand(move.base(), move.disp() + sizeof(float));
 }
 #endif
 
+// Resolves the pending_ list to a list in orderedMoves_.
 bool
 MoveResolver::resolve()
 {
     resetState();
     orderedMoves_.clear();
 
+    // Upon return from this function, the pending_ list must be cleared.
+    auto clearPending = mozilla::MakeScopeExit([this]() {
+        pending_.clear();
+    });
+
 #ifdef JS_CODEGEN_ARM
     // Some of ARM's double registers alias two of its single registers,
     // but the algorithm below assumes that every register can participate
     // in at most one cycle. To satisfy the algorithm, any double registers
     // that may conflict are split into their single-register halves.
     //
     // This logic is only applicable because ARM only uses registers d0-d15,
     // all of which alias s0-s31. Double registers d16-d31 are unused.
--- a/js/src/jit/MoveResolver.h
+++ b/js/src/jit/MoveResolver.h
@@ -328,16 +328,19 @@ class MoveResolver
         return orderedMoves_.length();
     }
     const MoveOp& getMove(size_t i) const {
         return orderedMoves_[i];
     }
     uint32_t numCycles() const {
         return numCycles_;
     }
+    bool hasNoPendingMoves() const {
+        return pending_.empty();
+    }
     void setAllocator(TempAllocator& alloc) {
         movePool_.setAllocator(alloc);
     }
 };
 
 } // namespace jit
 } // namespace js
 
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -4703,17 +4703,17 @@ MacroAssembler::callWithABIPre(uint32_t*
                                              ABIStackAlignment);
     }
 
     *stackAdjust = stackForCall;
     reserveStack(stackForCall);
 
     // Position all arguments.
     {
-        enoughMemory_ = enoughMemory_ && moveResolver_.resolve();
+        enoughMemory_ &= moveResolver_.resolve();
         if (!enoughMemory_)
             return;
 
         MoveEmitter emitter(*this);
         emitter.emit(moveResolver_);
         emitter.finish();
     }
 
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -2186,17 +2186,17 @@ MacroAssembler::callWithABIPre(uint32_t*
 
     // Save $ra because call is going to clobber it. Restore it in
     // callWithABIPost. NOTE: This is needed for calls from SharedIC.
     // Maybe we can do this differently.
     storePtr(ra, Address(StackPointer, stackForCall - sizeof(intptr_t)));
 
     // Position all arguments.
     {
-        enoughMemory_ = enoughMemory_ && moveResolver_.resolve();
+        enoughMemory_ &= moveResolver_.resolve();
         if (!enoughMemory_)
             return;
 
         MoveEmitter emitter(*this);
         emitter.emit(moveResolver_);
         emitter.finish();
     }
 
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -2035,17 +2035,17 @@ MacroAssembler::callWithABIPre(uint32_t*
 
     // Save $ra because call is going to clobber it. Restore it in
     // callWithABIPost. NOTE: This is needed for calls from SharedIC.
     // Maybe we can do this differently.
     storePtr(ra, Address(StackPointer, stackForCall - sizeof(intptr_t)));
 
     // Position all arguments.
     {
-        enoughMemory_ = enoughMemory_ && moveResolver_.resolve();
+        enoughMemory_ &= moveResolver_.resolve();
         if (!enoughMemory_)
             return;
 
         MoveEmitter emitter(*this);
         emitter.emit(moveResolver_);
         emitter.finish();
     }
 
--- a/js/src/jsapi-tests/testBug604087.cpp
+++ b/js/src/jsapi-tests/testBug604087.cpp
@@ -14,17 +14,17 @@
 
 const js::Class OuterWrapperClass = PROXY_CLASS_DEF(
     "Proxy",
     JSCLASS_HAS_RESERVED_SLOTS(1) /* additional class flags */);
 
 static JSObject*
 wrap(JSContext* cx, JS::HandleObject toWrap, JS::HandleObject target)
 {
-    JSAutoCompartment ac(cx, target);
+    JSAutoRealm ar(cx, target);
     JS::RootedObject wrapper(cx, toWrap);
     if (!JS_WrapObject(cx, &wrapper))
         return nullptr;
     return wrapper;
 }
 
 static void
 PreWrap(JSContext* cx, JS::HandleObject scope, JS::HandleObject obj,
@@ -75,17 +75,17 @@ BEGIN_TEST(testBug604087)
 
     JS::RootedObject c4wrapper(cx, wrap(cx, outerObj, compartment4));
     CHECK(c4wrapper);
     c4wrapper->as<js::ProxyObject>().setReservedSlot(0, js::Int32Value(4));
     compartment4 = c4wrapper = nullptr;
 
     JS::RootedObject next(cx);
     {
-        JSAutoCompartment ac(cx, compartment2);
+        JSAutoRealm ar(cx, compartment2);
         next = js::Wrapper::New(cx, compartment2, &js::Wrapper::singleton, options);
         CHECK(next);
     }
 
     JS_SetWrapObjectCallbacks(cx, &WrapObjectCallbacks);
     CHECK(JS_TransplantObject(cx, outerObj, next));
     return true;
 }
--- a/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
+++ b/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
@@ -58,17 +58,17 @@ BEGIN_TEST(test_CallNonGenericMethodOnPr
   // Now create the second global object and compartment...
   {
     JS::CompartmentOptions options;
     JS::RootedObject globalB(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
 						    JS::FireOnNewGlobalHook, options));
     CHECK(globalB);
 
     // ...and enter it.
-    JSAutoCompartment enter(cx, globalB);
+    JSAutoRealm enter(cx, globalB);
     JS::RootedObject customB(cx, JS_NewObject(cx, &CustomClass));
     CHECK(customB);
     JS_SetReservedSlot(customB, CUSTOM_SLOT, Int32Value(42));
 
     JS::RootedFunction customMethodB(cx, JS_NewFunction(cx, CustomMethod, 0, 0,
 							"customMethodB"));
     CHECK(customMethodB);
 
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -33,17 +33,17 @@ static JS::PersistentRootedObject truste
 
 static bool
 CallTrusted(JSContext* cx, unsigned argc, JS::Value* vp)
 {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
 
     bool ok = false;
     {
-        JSAutoCompartment ac(cx, trusted_glob);
+        JSAutoRealm ar(cx, trusted_glob);
         JS::RootedValue funVal(cx, JS::ObjectValue(*trusted_fun));
         ok = JS_CallFunctionValue(cx, nullptr, funVal, JS::HandleValueArray::empty(), args.rval());
     }
     return ok;
 }
 
 BEGIN_TEST(testChromeBuffer)
 {
@@ -61,17 +61,17 @@ BEGIN_TEST(testChromeBuffer)
      * compiled with "trusted principals" can run using reserved trusted-only
      * buffer space.
      */
     {
         // Disable the JIT because if we don't this test fails.  See bug 1160414.
         JS::ContextOptions oldOptions = JS::ContextOptionsRef(cx);
         JS::ContextOptionsRef(cx).setIon(false).setBaseline(false);
         {
-            JSAutoCompartment ac(cx, trusted_glob);
+            JSAutoRealm ar(cx, trusted_glob);
             const char* paramName = "x";
             const char* bytes = "return x ? 1 + trusted(x-1) : 0";
             JS::CompileOptions options(cx);
             options.setFileAndLine("", 0);
             JS::AutoObjectVector emptyScopeChain(cx);
             CHECK(JS::CompileFunction(cx, emptyScopeChain, options, "trusted",
                                       1, &paramName, bytes, strlen(bytes), &fun));
             CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun, JSPROP_ENUMERATE));
@@ -105,17 +105,17 @@ BEGIN_TEST(testChromeBuffer)
     }
 
     /*
      * Check that content called from chrome in the reserved-buffer space
      * immediately ooms.
      */
     {
         {
-            JSAutoCompartment ac(cx, trusted_glob);
+            JSAutoRealm ar(cx, trusted_glob);
             const char* paramName = "untrusted";
             const char* bytes = "try {                                  "
                                 "  untrusted();                         "
                                 "} catch (e) {                          "
                                 "  /*                                   "
                                 "   * Careful!  We must not reenter JS  "
                                 "   * that might try to push a frame.   "
                                 "   */                                  "
@@ -151,17 +151,17 @@ BEGIN_TEST(testChromeBuffer)
         CHECK(JS_CallFunction(cx, nullptr, fun, JS::HandleValueArray(v), &rval));
         bool match;
         CHECK(JS_StringEqualsAscii(cx, rval.toString(), "From trusted: InternalError: too much recursion", &match));
         CHECK(match);
     }
 
     {
         {
-            JSAutoCompartment ac(cx, trusted_glob);
+            JSAutoRealm ar(cx, trusted_glob);
             const char* bytes = "return 42";
             JS::CompileOptions options(cx);
             options.setFileAndLine("", 0);
             JS::AutoObjectVector emptyScopeChain(cx);
             CHECK(JS::CompileFunction(cx, emptyScopeChain, options, "trusted",
                                       0, nullptr, bytes, strlen(bytes), &fun));
             CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun, JSPROP_ENUMERATE));
             trusted_fun = JS_GetFunctionObject(fun);
--- a/js/src/jsapi-tests/testCloneScript.cpp
+++ b/js/src/jsapi-tests/testCloneScript.cpp
@@ -26,29 +26,29 @@ BEGIN_TEST(test_cloneScript)
         "    ++i;\n"
         "}\n"
         "(sum);\n";
 
     JS::RootedObject obj(cx);
 
     // compile for A
     {
-        JSAutoCompartment a(cx, A);
+        JSAutoRealm a(cx, A);
         JS::RootedFunction fun(cx);
         JS::CompileOptions options(cx);
         options.setFileAndLine(__FILE__, 1);
         JS::AutoObjectVector emptyScopeChain(cx);
         CHECK(JS::CompileFunction(cx, emptyScopeChain, options, "f", 0, nullptr,
                                   source, strlen(source), &fun));
         CHECK(obj = JS_GetFunctionObject(fun));
     }
 
     // clone into B
     {
-        JSAutoCompartment b(cx, B);
+        JSAutoRealm b(cx, B);
         CHECK(JS::CloneFunctionObject(cx, obj));
     }
 
     return true;
 }
 END_TEST(test_cloneScript)
 
 struct Principals final : public JSPrincipals
@@ -107,17 +107,17 @@ BEGIN_TEST(test_cloneScriptWithPrincipal
 
     const char* argnames[] = { "arg" };
     const char* source = "return function() { return arg; }";
 
     JS::RootedObject obj(cx);
 
     // Compile in A
     {
-        JSAutoCompartment a(cx, A);
+        JSAutoRealm a(cx, A);
         JS::CompileOptions options(cx);
         options.setFileAndLine(__FILE__, 1);
         JS::RootedFunction fun(cx);
         JS::AutoObjectVector emptyScopeChain(cx);
         JS::CompileFunction(cx, emptyScopeChain, options, "f",
                            mozilla::ArrayLength(argnames), argnames, source,
                            strlen(source), &fun);
         CHECK(fun);
@@ -126,17 +126,17 @@ BEGIN_TEST(test_cloneScriptWithPrincipal
         CHECK(script = JS_GetFunctionScript(cx, fun));
 
         CHECK(JS_GetScriptPrincipals(script) == principalsA);
         CHECK(obj = JS_GetFunctionObject(fun));
     }
 
     // Clone into B
     {
-        JSAutoCompartment b(cx, B);
+        JSAutoRealm b(cx, B);
         JS::RootedObject cloned(cx);
         CHECK(cloned = JS::CloneFunctionObject(cx, obj));
 
         JS::RootedFunction fun(cx);
         JS::RootedValue clonedValue(cx, JS::ObjectValue(*cloned));
         CHECK(fun = JS_ValueToFunction(cx, clonedValue));
 
         JSScript* script;
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -14,17 +14,17 @@ BEGIN_TEST(testDebugger_newScriptHook)
 {
     // Test that top-level indirect eval fires the newScript hook.
     CHECK(JS_DefineDebuggerObject(cx, global));
     JS::CompartmentOptions options;
     JS::RootedObject g(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
                                               JS::FireOnNewGlobalHook, options));
     CHECK(g);
     {
-        JSAutoCompartment ae(cx, g);
+        JSAutoRealm ae(cx, g);
         CHECK(JS_InitStandardClasses(cx, g));
     }
 
     JS::RootedObject gWrapper(cx, g);
     CHECK(JS_WrapObject(cx, &gWrapper));
     JS::RootedValue v(cx, JS::ObjectValue(*gWrapper));
     CHECK(JS_SetProperty(cx, global, "g", v));
 
@@ -43,17 +43,17 @@ BEGIN_TEST(testDebugger_newScriptHook)
     return testIndirectEval(g, "Math.abs(0)");
 }
 
 bool testIndirectEval(JS::HandleObject scope, const char* code)
 {
     EXEC("hits = 0;");
 
     {
-        JSAutoCompartment ae(cx, scope);
+        JSAutoRealm ae(cx, scope);
         JSString* codestr = JS_NewStringCopyZ(cx, code);
         CHECK(codestr);
         JS::RootedValue arg(cx, JS::StringValue(codestr));
         JS::RootedValue v(cx);
         CHECK(JS_CallFunctionName(cx, scope, "eval", HandleValueArray(arg), &v));
     }
 
     JS::RootedValue hitsv(cx);
--- a/js/src/jsapi-tests/testFreshGlobalEvalRedefinition.cpp
+++ b/js/src/jsapi-tests/testFreshGlobalEvalRedefinition.cpp
@@ -28,17 +28,17 @@ BEGIN_TEST(testRedefineGlobalEval)
     };
 
     /* Create the global object. */
     JS::CompartmentOptions options;
     JS::Rooted<JSObject*> g(cx, JS_NewGlobalObject(cx, &cls, nullptr, JS::FireOnNewGlobalHook, options));
     if (!g)
         return false;
 
-    JSAutoCompartment ac(cx, g);
+    JSAutoRealm ar(cx, g);
     JS::Rooted<JS::Value> v(cx);
     CHECK(JS_GetProperty(cx, g, "Object", &v));
 
     static const char data[] = "Object.defineProperty(this, 'eval', { configurable: false });";
     JS::CompileOptions opts(cx);
     CHECK(JS::Evaluate(cx, opts.setFileAndLine(__FILE__, __LINE__),
                        data, mozilla::ArrayLength(data) - 1, &v));
 
--- a/js/src/jsapi-tests/testGCGrayMarking.cpp
+++ b/js/src/jsapi-tests/testGCGrayMarking.cpp
@@ -40,17 +40,17 @@ BEGIN_TEST(testGCGrayMarking)
 {
     AutoNoAnalysisForTest disableAnalysis;
     AutoDisableCompactingGC disableCompactingGC(cx);
 #ifdef JS_GC_ZEAL
     AutoLeaveZeal nozeal(cx);
 #endif /* JS_GC_ZEAL */
 
     CHECK(InitGlobals());
-    JSAutoCompartment ac(cx, global1);
+    JSAutoRealm ar(cx, global1);
 
     InitGrayRootTracer();
 
     bool ok =
         TestMarking() &&
         TestWeakMaps() &&
         TestUnassociatedWeakMaps() &&
         TestCCWs() &&
@@ -652,17 +652,17 @@ AllocSameCompartmentSourceObject(JSObjec
     return source;
 }
 
 JSObject*
 GetCrossCompartmentWrapper(JSObject* target)
 {
     MOZ_ASSERT(target->compartment() == global1->compartment());
     JS::RootedObject obj(cx, target);
-    JSAutoCompartment ac(cx, global2);
+    JSAutoRealm ar(cx, global2);
     if (!JS_WrapObject(cx, &obj))
         return nullptr;
 
     EvictNursery();
 
     MOZ_ASSERT(obj->compartment() == global2->compartment());
     return obj;
 }
--- a/js/src/jsapi-tests/testGCMarking.cpp
+++ b/js/src/jsapi-tests/testGCMarking.cpp
@@ -40,17 +40,17 @@ ConstructCCW(JSContext* cx, const JSClas
     // This checks that the API obeys the implicit zone request.
     if (global1->zone() == global2->zone()) {
         fprintf(stderr, "global2 is in global1's zone");
         return false;
     }
 
     // Define an object in compartment 2, that is wrapped by a CCW into compartment 1.
     {
-        JSAutoCompartment ac(cx, global2);
+        JSAutoRealm ar(cx, global2);
         wrappee.set(JS_NewPlainObject(cx));
         if (wrappee->compartment() != global2->compartment()) {
             fprintf(stderr, "wrappee in wrong compartment");
             return false;
         }
     }
 
     wrapper.set(wrappee);
--- a/js/src/jsapi-tests/testMutedErrors.cpp
+++ b/js/src/jsapi-tests/testMutedErrors.cpp
@@ -41,17 +41,17 @@ eval(const char* asciiChars, bool mutedE
     for (size_t i = 0; i < len; ++i)
         chars[i] = asciiChars[i];
     chars[len] = 0;
 
     JS::CompartmentOptions globalOptions;
     JS::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
 						   JS::FireOnNewGlobalHook, globalOptions));
     CHECK(global);
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
     CHECK(JS_InitStandardClasses(cx, global));
 
 
     JS::CompileOptions options(cx);
     options.setMutedErrors(mutedErrors)
            .setFileAndLine("", 0);
 
     return JS::Evaluate(cx, options, chars.get(), len, rval);
--- a/js/src/jsapi-tests/testPreserveJitCode.cpp
+++ b/js/src/jsapi-tests/testPreserveJitCode.cpp
@@ -36,17 +36,17 @@ bool
 testPreserveJitCode(bool preserveJitCode, unsigned remainingIonScripts)
 {
     cx->options().setBaseline(true);
     cx->options().setIon(true);
     cx->runtime()->setOffthreadIonCompilationEnabled(false);
 
     RootedObject global(cx, createTestGlobal(preserveJitCode));
     CHECK(global);
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     // The Ion JIT may be unavailable due to --disable-ion or lack of support
     // for this platform.
     if (!js::jit::IsIonEnabled(cx))
         knownFail = true;
 
     CHECK_EQUAL(countIonScripts(global), 0u);
 
--- a/js/src/jsapi-tests/testScriptObject.cpp
+++ b/js/src/jsapi-tests/testScriptObject.cpp
@@ -180,17 +180,17 @@ BEGIN_FIXTURE_TEST(ScriptObjectFixture, 
     options.setFileAndLine(__FILE__, __LINE__);
     CHECK(JS_CompileScript(cx, "val", 3, options, &script));
     JS::RootedValue value(cx);
     CHECK(JS_ExecuteScript(cx, script, &value));
     CHECK(value.toInt32() == 42);
     {
         JS::RootedObject global2(cx, createGlobal());
         CHECK(global2);
-        JSAutoCompartment ac(cx, global2);
+        JSAutoRealm ar(cx, global2);
         CHECK(JS_WrapValue(cx, &fortyTwo));
         CHECK(JS_SetProperty(cx, global, "val", fortyTwo));
         JS::RootedValue value2(cx);
         CHECK(JS::CloneAndExecuteScript(cx, script, &value2));
         CHECK(value2.toInt32() == 42);
     }
     JS::RootedValue value3(cx);
     CHECK(JS_ExecuteScript(cx, script, &value3));
--- a/js/src/jsapi-tests/testStructuredClone.cpp
+++ b/js/src/jsapi-tests/testStructuredClone.cpp
@@ -14,27 +14,27 @@ BEGIN_TEST(testStructuredClone_object)
     JS::RootedObject g1(cx, createGlobal());
     JS::RootedObject g2(cx, createGlobal());
     CHECK(g1);
     CHECK(g2);
 
     JS::RootedValue v1(cx);
 
     {
-        JSAutoCompartment ac(cx, g1);
+        JSAutoRealm ar(cx, g1);
         JS::RootedValue prop(cx, JS::Int32Value(1337));
 
         JS::RootedObject obj(cx, JS_NewPlainObject(cx));
         v1 = JS::ObjectOrNullValue(obj);
         CHECK(v1.isObject());
         CHECK(JS_SetProperty(cx, obj, "prop", prop));
     }
 
     {
-        JSAutoCompartment ac(cx, g2);
+        JSAutoRealm ar(cx, g2);
         JS::RootedValue v2(cx);
 
         CHECK(JS_StructuredClone(cx, v1, &v2, nullptr, nullptr));
         CHECK(v2.isObject());
         JS::RootedObject obj(cx, &v2.toObject());
 
         JS::RootedValue prop(cx);
         CHECK(JS_GetProperty(cx, obj, "prop", &prop));
@@ -52,26 +52,26 @@ BEGIN_TEST(testStructuredClone_string)
     JS::RootedObject g1(cx, createGlobal());
     JS::RootedObject g2(cx, createGlobal());
     CHECK(g1);
     CHECK(g2);
 
     JS::RootedValue v1(cx);
 
     {
-        JSAutoCompartment ac(cx, g1);
+        JSAutoRealm ar(cx, g1);
         JS::RootedValue prop(cx, JS::Int32Value(1337));
 
         v1 = JS::StringValue(JS_NewStringCopyZ(cx, "Hello World!"));
         CHECK(v1.isString());
         CHECK(v1.toString());
     }
 
     {
-        JSAutoCompartment ac(cx, g2);
+        JSAutoRealm ar(cx, g2);
         JS::RootedValue v2(cx);
 
         CHECK(JS_StructuredClone(cx, v1, &v2, nullptr, nullptr));
         CHECK(v2.isString());
         CHECK(v2.toString());
 
         JS::RootedValue expected(cx, JS::StringValue(
             JS_NewStringCopyZ(cx, "Hello World!")));
@@ -88,28 +88,28 @@ BEGIN_TEST(testStructuredClone_externalA
     JS::RootedObject g1(cx, createGlobal());
     JS::RootedObject g2(cx, createGlobal());
     CHECK(g1);
     CHECK(g2);
 
     JS::RootedValue v1(cx);
 
     {
-        JSAutoCompartment ac(cx, g1);
+        JSAutoRealm ar(cx, g1);
 
         JS::RootedObject obj(cx, JS_NewExternalArrayBuffer(cx, data.len(), data.contents(),
             &ExternalData::freeCallback, &data));
         CHECK(!data.wasFreed());
 
         v1 = JS::ObjectOrNullValue(obj);
         CHECK(v1.isObject());
     }
 
     {
-        JSAutoCompartment ac(cx, g2);
+        JSAutoRealm ar(cx, g2);
         JS::RootedValue v2(cx);
 
         CHECK(JS_StructuredClone(cx, v1, &v2, nullptr, nullptr));
         CHECK(v2.isObject());
 
         JS::RootedObject obj(cx, &v2.toObject());
         CHECK(&v1.toObject() != obj);
 
@@ -264,17 +264,17 @@ BEGIN_TEST(testStructuredClone_SavedFram
 
     for (auto* pp = principalsToTest; pp->principals != DONE; pp++) {
         fprintf(stderr, "Testing with principals '%s'\n", pp->name);
 
 	JS::CompartmentOptions options;
         JS::RootedObject g(cx, JS_NewGlobalObject(cx, getGlobalClass(), pp->principals,
                                                   JS::FireOnNewGlobalHook, options));
         CHECK(g);
-        JSAutoCompartment ac(cx, g);
+        JSAutoRealm ar(cx, g);
 
         CHECK(js::DefineTestingFunctions(cx, g, false, false));
 
         JS::RootedValue srcVal(cx);
         CHECK(evaluate("(function one() {                      \n"  // 1
                        "  return (function two() {             \n"  // 2
                        "    return (function three() {         \n"  // 3
                        "      return saveStack();              \n"  // 4
--- a/js/src/jsapi-tests/testUbiNode.cpp
+++ b/js/src/jsapi-tests/testUbiNode.cpp
@@ -89,17 +89,17 @@ BEGIN_TEST(test_ubiNodeZone)
     RootedString string1(cx, JS_NewStringCopyZ(cx, "Simpson's Individual Stringettes!"));
     CHECK(string1);
     RootedScript script1(cx);
     CHECK(JS::Compile(cx, options, "", 0, &script1));
 
     {
         // ... and then enter global2's zone and create a string and script
         // there, too.
-        JSAutoCompartment ac(cx, global2);
+        JSAutoRealm ar(cx, global2);
 
         RootedString string2(cx, JS_NewStringCopyZ(cx, "A million household uses!"));
         CHECK(string2);
         RootedScript script2(cx);
         CHECK(JS::Compile(cx, options, "", 0, &script2));
 
         CHECK(JS::ubi::Node(string1).zone() == global1->zone());
         CHECK(JS::ubi::Node(script1).zone() == global1->zone());
@@ -124,24 +124,24 @@ BEGIN_TEST(test_ubiNodeCompartment)
                                                 JS::FireOnNewGlobalHook, globalOptions));
     CHECK(global2);
     CHECK(global1->compartment() != global2->compartment());
     CHECK(JS::ubi::Node(global2).compartment() == global2->compartment());
     CHECK(JS::ubi::Node(global2).compartment() != global1->compartment());
 
     JS::CompileOptions options(cx);
 
-    // Create a script in the original compartment...
+    // Create a script in the original realm...
     RootedScript script1(cx);
     CHECK(JS::Compile(cx, options, "", 0, &script1));
 
     {
-        // ... and then enter global2's compartment and create a script
+        // ... and then enter global2's realm and create a script
         // there, too.
-        JSAutoCompartment ac(cx, global2);
+        JSAutoRealm ar(cx, global2);
 
         RootedScript script2(cx);
         CHECK(JS::Compile(cx, options, "", 0, &script2));
 
         CHECK(JS::ubi::Node(script1).compartment() == global1->compartment());
         CHECK(JS::ubi::Node(script2).compartment() == global2->compartment());
     }
 
--- a/js/src/jsapi-tests/testWeakMap.cpp
+++ b/js/src/jsapi-tests/testWeakMap.cpp
@@ -81,17 +81,17 @@ BEGIN_TEST(testWeakMap_keyDelegates)
     CHECK(key);
 
     JS::RootedObject delegate(cx, newDelegate());
     CHECK(delegate);
     keyDelegate = delegate;
 
     JS::RootedObject delegateRoot(cx);
     {
-        JSAutoCompartment ac(cx, delegate);
+        JSAutoRealm ar(cx, delegate);
         delegateRoot = JS_NewPlainObject(cx);
         CHECK(delegateRoot);
         JS::RootedValue delegateValue(cx, JS::ObjectValue(*delegate));
         CHECK(JS_DefineProperty(cx, delegateRoot, "delegate", delegateValue, 0));
     }
     delegate = nullptr;
 
     /*
@@ -180,23 +180,23 @@ JSObject* newCCW(JS::HandleObject source
 {
     /*
      * Now ensure that this zone will be swept first by adding a cross
      * compartment wrapper to a new objct in the same zone as the
      * delegate obejct.
      */
     JS::RootedObject object(cx);
     {
-        JSAutoCompartment ac(cx, destZone);
+        JSAutoRealm ar(cx, destZone);
         object = JS_NewPlainObject(cx);
         if (!object)
             return nullptr;
     }
     {
-        JSAutoCompartment ac(cx, sourceZone);
+        JSAutoRealm ar(cx, sourceZone);
         if (!JS_WrapObject(cx, &object))
             return nullptr;
     }
 
     // In order to test the SCC algorithm, we need the wrapper/wrappee to be
     // tenured.
     cx->runtime()->gc.evictNursery();
 
--- a/js/src/jsapi-tests/tests.cpp
+++ b/js/src/jsapi-tests/tests.cpp
@@ -87,17 +87,17 @@ JSObject* JSAPITest::createGlobal(JSPrin
 #ifdef ENABLE_STREAMS
     options.creationOptions().setStreamsEnabled(true);
 #endif
     newGlobal = JS_NewGlobalObject(cx, getGlobalClass(), principals, JS::FireOnNewGlobalHook,
                                    options);
     if (!newGlobal)
         return nullptr;
 
-    JSAutoCompartment ac(cx, newGlobal);
+    JSAutoRealm ar(cx, newGlobal);
 
     // Populate the global object with the standard globals like Object and
     // Array.
     if (!JS_InitStandardClasses(cx, newGlobal))
         return nullptr;
 
     global = newGlobal;
     return newGlobal;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -688,56 +688,56 @@ JS_EnterCompartment(JSContext* cx, JSObj
 JS_PUBLIC_API(void)
 JS_LeaveCompartment(JSContext* cx, JSCompartment* oldCompartment)
 {
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     cx->leaveCompartment(oldCompartment);
 }
 
-JSAutoCompartment::JSAutoCompartment(JSContext* cx, JSObject* target
-                                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+JSAutoRealm::JSAutoRealm(JSContext* cx, JSObject* target
+                         MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   : cx_(cx),
     oldCompartment_(cx->compartment())
 {
     AssertHeapIsIdleOrIterating();
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     cx_->enterCompartmentOf(target);
 }
 
-JSAutoCompartment::JSAutoCompartment(JSContext* cx, JSScript* target
-                                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+JSAutoRealm::JSAutoRealm(JSContext* cx, JSScript* target
+                         MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   : cx_(cx),
     oldCompartment_(cx->compartment())
 {
     AssertHeapIsIdleOrIterating();
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     cx_->enterCompartmentOf(target);
 }
 
-JSAutoCompartment::~JSAutoCompartment()
+JSAutoRealm::~JSAutoRealm()
 {
     cx_->leaveCompartment(oldCompartment_);
 }
 
-JSAutoNullableCompartment::JSAutoNullableCompartment(JSContext* cx,
-                                                     JSObject* targetOrNull
-                                                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+JSAutoNullableRealm::JSAutoNullableRealm(JSContext* cx,
+                                         JSObject* targetOrNull
+                                         MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   : cx_(cx),
     oldCompartment_(cx->compartment())
 {
     AssertHeapIsIdleOrIterating();
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     if (targetOrNull)
         cx_->enterCompartmentOf(targetOrNull);
     else
         cx_->enterNullCompartment();
 }
 
-JSAutoNullableCompartment::~JSAutoNullableCompartment()
+JSAutoNullableRealm::~JSAutoNullableRealm()
 {
     cx_->leaveCompartment(oldCompartment_);
 }
 
 JS_PUBLIC_API(void)
 JS_SetCompartmentPrivate(JSCompartment* compartment, void* data)
 {
     compartment->data = data;
@@ -4934,31 +4934,28 @@ JS::Evaluate(JSContext* cx, AutoObjectVe
 
 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(JSFunction*)
-JS::GetModuleResolveHook(JSContext* cx)
-{
-    AssertHeapIsIdle();
-    CHECK_REQUEST(cx);
-    return cx->global()->moduleResolveHook();
+JS_PUBLIC_API(JS::ModuleResolveHook)
+JS::GetModuleResolveHook(JSRuntime* rt)
+{
+    AssertHeapIsIdle();
+    return rt->moduleResolveHook;
 }
 
 JS_PUBLIC_API(void)
-JS::SetModuleResolveHook(JSContext* cx, HandleFunction func)
-{
-    AssertHeapIsIdle();
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, func);
-    cx->global()->setModuleResolveHook(func);
+JS::SetModuleResolveHook(JSRuntime* rt, JS::ModuleResolveHook func)
+{
+    AssertHeapIsIdle();
+    rt->moduleResolveHook = func;
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
                   SourceBufferHolder& srcBuf, JS::MutableHandleObject module)
 {
     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle();
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1244,75 +1244,73 @@ JS_WrapValue(JSContext* cx, JS::MutableH
 
 extern JS_PUBLIC_API(JSObject*)
 JS_TransplantObject(JSContext* cx, JS::HandleObject origobj, JS::HandleObject target);
 
 extern JS_PUBLIC_API(bool)
 JS_RefreshCrossCompartmentWrappers(JSContext* cx, JS::Handle<JSObject*> obj);
 
 /*
- * At any time, a JSContext has a current (possibly-nullptr) compartment.
- * Compartments are described in:
+ * At any time, a JSContext has a current (possibly-nullptr) realm.
+ * Realms are described in:
  *
  *   developer.mozilla.org/en-US/docs/SpiderMonkey/SpiderMonkey_compartments
  *
- * The current compartment of a context may be changed. The preferred way to do
- * this is with JSAutoCompartment:
+ * The current realm of a context may be changed. The preferred way to do
+ * this is with JSAutoRealm:
  *
  *   void foo(JSContext* cx, JSObject* obj) {
- *     // in some compartment 'c'
+ *     // in some realm 'r'
  *     {
- *       JSAutoCompartment ac(cx, obj);  // constructor enters
- *       // in the compartment of 'obj'
+ *       JSAutoRealm ar(cx, obj);  // constructor enters
+ *       // in the realm of 'obj'
  *     }                                 // destructor leaves
- *     // back in compartment 'c'
+ *     // back in realm 'r'
  *   }
  *
  * For more complicated uses that don't neatly fit in a C++ stack frame, the
- * compartment can entered and left using separate function calls:
+ * realm can be entered and left using separate function calls:
  *
  *   void foo(JSContext* cx, JSObject* obj) {
  *     // in 'oldCompartment'
  *     JSCompartment* oldCompartment = JS_EnterCompartment(cx, obj);
  *     // in the compartment of 'obj'
  *     JS_LeaveCompartment(cx, oldCompartment);
  *     // back in 'oldCompartment'
  *   }
  *
  * Note: these calls must still execute in a LIFO manner w.r.t all other
  * enter/leave calls on the context. Furthermore, only the return value of a
  * JS_EnterCompartment call may be passed as the 'oldCompartment' argument of
  * the corresponding JS_LeaveCompartment call.
  *
- * Entering a compartment roots the compartment and its global object for the
- * lifetime of the JSAutoCompartment.
- */
-
-class MOZ_RAII JS_PUBLIC_API(JSAutoCompartment)
+ * Entering a realm roots the realm and its global object for the lifetime of
+ * the JSAutoRealm.
+ */
+
+class MOZ_RAII JS_PUBLIC_API(JSAutoRealm)
 {
     JSContext* cx_;
     JSCompartment* oldCompartment_;
   public:
-    JSAutoCompartment(JSContext* cx, JSObject* target
-                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
-    JSAutoCompartment(JSContext* cx, JSScript* target
-                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
-    ~JSAutoCompartment();
+    JSAutoRealm(JSContext* cx, JSObject* target MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+    JSAutoRealm(JSContext* cx, JSScript* target MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+    ~JSAutoRealm();
 
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
-class MOZ_RAII JS_PUBLIC_API(JSAutoNullableCompartment)
+class MOZ_RAII JS_PUBLIC_API(JSAutoNullableRealm)
 {
     JSContext* cx_;
     JSCompartment* oldCompartment_;
   public:
-    explicit JSAutoNullableCompartment(JSContext* cx, JSObject* targetOrNull
-                                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
-    ~JSAutoNullableCompartment();
+    explicit JSAutoNullableRealm(JSContext* cx, JSObject* targetOrNull
+                                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+    ~JSAutoNullableRealm();
 
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 /** NB: This API is infallible; a nullptr return value does not indicate error.
  *
  * Entering a compartment roots the compartment and its global object until the
  * matching JS_LeaveCompartment() call.
@@ -4138,27 +4136,29 @@ Evaluate(JSContext* cx, const ReadOnlyCo
 
 /**
  * Evaluate the given file in the scope of the current global of cx.
  */
 extern JS_PUBLIC_API(bool)
 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
          const char* filename, JS::MutableHandleValue rval);
 
-/**
- * Get the HostResolveImportedModule hook for a global.
- */
-extern JS_PUBLIC_API(JSFunction*)
-GetModuleResolveHook(JSContext* cx);
-
-/**
- * Set the HostResolveImportedModule hook for a global to the given function.
+using ModuleResolveHook = JSObject* (*)(JSContext*, HandleObject, HandleString);
+
+/**
+ * Get the HostResolveImportedModule hook for the runtime.
+ */
+extern JS_PUBLIC_API(ModuleResolveHook)
+GetModuleResolveHook(JSRuntime* rt);
+
+/**
+ * Set the HostResolveImportedModule hook for the runtime to the given function.
  */
 extern JS_PUBLIC_API(void)
-SetModuleResolveHook(JSContext* cx, JS::HandleFunction func);
+SetModuleResolveHook(JSRuntime* rt, ModuleResolveHook func);
 
 /**
  * Parse the given source buffer as a module in the scope of the current global
  * of cx and return a source text module record.
  */
 extern JS_PUBLIC_API(bool)
 CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
               SourceBufferHolder& srcBuf, JS::MutableHandleObject moduleRecord);
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -846,17 +846,17 @@ static JS::UniqueChars
 FormatFrame(JSContext* cx, const FrameIter& iter, JS::UniqueChars&& inBuf, int num,
             bool showArgs, bool showLocals, bool showThisProps)
 {
     MOZ_ASSERT(!cx->isExceptionPending());
     RootedScript script(cx, iter.script());
     jsbytecode* pc = iter.pc();
 
     RootedObject envChain(cx, iter.environmentChain(cx));
-    JSAutoCompartment ac(cx, envChain);
+    JSAutoRealm ar(cx, envChain);
 
     const char* filename = script->filename();
     unsigned lineno = PCToLineNumber(script, pc);
     RootedFunction fun(cx, iter.maybeCallee(cx));
     RootedString funname(cx);
     if (fun)
         funname = fun->displayAtom();
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -605,17 +605,18 @@ ShellContext::ShellContext(JSContext* cx
     lastWarning(cx, NullValue()),
     promiseRejectionTrackerCallback(cx, NullValue()),
     watchdogLock(mutexid::ShellContextWatchdog),
     exitCode(0),
     quitting(false),
     readLineBufPos(0),
     errFilePtr(nullptr),
     outFilePtr(nullptr),
-    offThreadMonitor(mutexid::ShellOffThreadState)
+    offThreadMonitor(mutexid::ShellOffThreadState),
+    moduleResolveHook(cx)
 {}
 
 ShellContext::~ShellContext()
 {
     MOZ_ASSERT(offThreadJobs.empty());
 }
 
 ShellContext*
@@ -721,17 +722,17 @@ ShellInterruptCallback(JSContext* cx)
     // Do this first to prevent other interrupts that may occur while the
     // user-supplied callback is executing from re-entering the handler.
     sc->serviceInterrupt = false;
 
     bool result;
     if (sc->haveInterruptFunc) {
         bool wasAlreadyThrowing = cx->isExceptionPending();
         JS::AutoSaveExceptionState savedExc(cx);
-        JSAutoCompartment ac(cx, &sc->interruptFunc.toObject());
+        JSAutoRealm ar(cx, &sc->interruptFunc.toObject());
         RootedValue rval(cx);
 
         // Report any exceptions thrown by the JS interrupt callback, but do
         // *not* keep it on the cx. The interrupt handler is invoked at points
         // that are not expected to throw catchable exceptions, like at
         // JSOP_RETRVAL.
         //
         // If the interrupted JS code was already throwing, any exceptions
@@ -863,16 +864,17 @@ RunBinAST(JSContext* cx, const char* fil
     return JS_ExecuteScript(cx, script);
 }
 
 #endif // JS_BUILD_BINAST
 
 static bool
 InitModuleLoader(JSContext* cx)
 {
+
     // Decompress and evaluate the embedded module loader source to initialize
     // the module loader for the current compartment.
 
     uint32_t srcLen = moduleloader::GetRawScriptsSize();
     ScopedJSFreePtr<char> src(cx->pod_malloc<char>(srcLen));
     if (!src || !DecompressString(moduleloader::compressedSources, moduleloader::GetCompressedSize(),
                                   reinterpret_cast<unsigned char*>(src.get()), srcLen))
     {
@@ -1939,17 +1941,17 @@ Evaluate(JSContext* cx, unsigned argc, V
             return false;
         if (!loadBuffer.append(loadData, loadLength)) {
             JS_ReportOutOfMemory(cx);
             return false;
         }
     }
 
     {
-        JSAutoCompartment ac(cx, global);
+        JSAutoRealm ar(cx, global);
         RootedScript script(cx);
 
         {
             if (saveBytecode) {
                 if (!JS::CompartmentCreationOptionsRef(cx).cloneSingletons()) {
                     JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr,
                                               JSSMSG_CACHE_SINGLETON_FAILED);
                     return false;
@@ -2008,17 +2010,17 @@ Evaluate(JSContext* cx, unsigned argc, V
         // delazified should be encoded at the end of the delazification.
         if (saveIncrementalBytecode) {
             if (!StartIncrementalEncoding(cx, script))
                 return false;
         }
 
         if (!JS_ExecuteScript(cx, envChain, script, args.rval())) {
             if (catchTermination && !JS_IsExceptionPending(cx)) {
-                JSAutoCompartment ac1(cx, callerGlobal);
+                JSAutoRealm ar1(cx, callerGlobal);
                 JSString* str = JS_NewStringCopyZ(cx, "terminated");
                 if (!str)
                     return false;
                 args.rval().setString(str);
                 return true;
             }
             return false;
         }
@@ -3012,17 +3014,17 @@ DisassembleToSprinter(JSContext* cx, uns
     DisassembleOptionParser p(args.length(), args.array());
     if (!p.parse(cx))
         return false;
 
     if (p.argc == 0) {
         /* Without arguments, disassemble the current script. */
         RootedScript script(cx, GetTopScript(cx));
         if (script) {
-            JSAutoCompartment ac(cx, script);
+            JSAutoRealm ar(cx, script);
             if (!Disassemble(cx, script, p.lines, sprinter))
                 return false;
             if (!SrcNotes(cx, script, sprinter))
                 return false;
             if (!TryNotes(cx, script, sprinter))
                 return false;
             if (!ScopeNotes(cx, script, sprinter))
                 return false;
@@ -3275,22 +3277,22 @@ Clone(JSContext* cx, unsigned argc, Valu
 
     if (args.length() == 0) {
         JS_ReportErrorASCII(cx, "Invalid arguments to clone");
         return false;
     }
 
     RootedObject funobj(cx);
     {
-        Maybe<JSAutoCompartment> ac;
+        Maybe<JSAutoRealm> ar;
         RootedObject obj(cx, args[0].isPrimitive() ? nullptr : &args[0].toObject());
 
         if (obj && obj->is<CrossCompartmentWrapperObject>()) {
             obj = UncheckedUnwrap(obj);
-            ac.emplace(cx, obj);
+            ar.emplace(cx, obj);
             args[0].setObject(*obj);
         }
         if (obj && obj->is<JSFunction>()) {
             funobj = obj;
         } else {
             JSFunction* fun = JS_ValueToFunction(cx, args[0]);
             if (!fun)
                 return false;
@@ -3427,17 +3429,17 @@ NewSandbox(JSContext* cx, bool lazy)
     JS::CompartmentOptions options;
     SetStandardCompartmentOptions(options);
     RootedObject obj(cx, JS_NewGlobalObject(cx, &sandbox_class, nullptr,
                                             JS::DontFireOnNewGlobalHook, options));
     if (!obj)
         return nullptr;
 
     {
-        JSAutoCompartment ac(cx, obj);
+        JSAutoRealm ar(cx, obj);
         if (!lazy && !JS_InitStandardClasses(cx, obj))
             return nullptr;
 
         RootedValue value(cx, BooleanValue(lazy));
         if (!JS_DefineProperty(cx, obj, "lazy", value, JSPROP_PERMANENT | JSPROP_READONLY))
             return nullptr;
 
         JS_FireOnNewGlobalObject(cx, obj);
@@ -3493,22 +3495,22 @@ EvalInContext(JSContext* cx, unsigned ar
         return true;
     }
 
     JS::AutoFilename filename;
     unsigned lineno;
 
     DescribeScriptedCaller(cx, &filename, &lineno);
     {
-        Maybe<JSAutoCompartment> ac;
+        Maybe<JSAutoRealm> ar;
         unsigned flags;
         JSObject* unwrapped = UncheckedUnwrap(sobj, true, &flags);
         if (flags & Wrapper::CROSS_COMPARTMENT) {
             sobj = unwrapped;
-            ac.emplace(cx, sobj);
+            ar.emplace(cx, sobj);
         }
 
         sobj = ToWindowIfWindowProxy(sobj);
 
         if (!(sobj->getClass()->flags & JSCLASS_IS_GLOBAL)) {
             JS_ReportErrorASCII(cx, "Invalid scope argument to evalcx");
             return false;
         }
@@ -3596,26 +3598,26 @@ WorkerMain(void* arg)
     js::UseInternalJobQueues(cx);
 
     if (!JS::InitSelfHostedCode(cx))
         return;
 
     EnvironmentPreparer environmentPreparer(cx);
 
     do {
-        JSAutoRequest ar(cx);
+        JSAutoRequest areq(cx);
 
         JS::CompartmentOptions compartmentOptions;
         SetStandardCompartmentOptions(compartmentOptions);
 
         RootedObject global(cx, NewGlobalObject(cx, compartmentOptions, nullptr));
         if (!global)
             break;
 
-        JSAutoCompartment ac(cx, global);
+        JSAutoRealm 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, input->length, &script))
@@ -4275,23 +4277,44 @@ SetModuleResolveHook(JSContext* cx, unsi
     }
 
     if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
         const char* typeName = InformalValueTypeName(args[0]);
         JS_ReportErrorASCII(cx, "expected hook function, got %s", typeName);
         return false;
     }
 
-    RootedFunction hook(cx, &args[0].toObject().as<JSFunction>());
-    Rooted<GlobalObject*> global(cx, cx->global());
-    global->setModuleResolveHook(hook);
+    ShellContext* sc = GetShellContext(cx);
+    sc->moduleResolveHook = &args[0].toObject().as<JSFunction>();
+
     args.rval().setUndefined();
     return true;
 }
 
+static JSObject*
+CallModuleResolveHook(JSContext* cx, HandleObject module, HandleString specifier)
+{
+    ShellContext* sc = GetShellContext(cx);
+
+    JS::AutoValueArray<2> args(cx);
+    args[0].setObject(*module);
+    args[1].setString(specifier);
+
+    RootedValue result(cx);
+    if (!JS_CallFunction(cx, nullptr, sc->moduleResolveHook, args, &result))
+        return nullptr;
+
+    if (!result.isObject() || !result.toObject().is<ModuleObject>()) {
+         JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
+         return nullptr;
+    }
+
+    return &result.toObject();
+}
+
 static bool
 GetModuleLoadPath(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     ShellContext* sc = GetShellContext(cx);
     if (sc->moduleLoadPath) {
         JSString* str = JS_NewStringCopyZ(cx, sc->moduleLoadPath.get());
@@ -5095,17 +5118,17 @@ DecompileThisScript(JSContext* cx, unsig
 
     NonBuiltinScriptFrameIter iter(cx);
     if (iter.done()) {
         args.rval().setString(cx->runtime()->emptyString);
         return true;
     }
 
     {
-        JSAutoCompartment ac(cx, iter.script());
+        JSAutoRealm ar(cx, iter.script());
 
         RootedScript script(cx, iter.script());
         JSString* result = JS_DecompileScript(cx, script);
         if (!result)
             return false;
 
         args.rval().setString(result);
     }
@@ -7575,21 +7598,21 @@ ErrorFilePointer()
 }
 
 static bool
 PrintStackTrace(JSContext* cx, HandleValue exn)
 {
     if (!exn.isObject())
         return false;
 
-    Maybe<JSAutoCompartment> ac;
+    Maybe<JSAutoRealm> ar;
     RootedObject exnObj(cx, &exn.toObject());
     if (IsCrossCompartmentWrapper(exnObj)) {
         exnObj = UncheckedUnwrap(exnObj);
-        ac.emplace(cx, exnObj);
+        ar.emplace(cx, exnObj);
     }
 
     // Ignore non-ErrorObject thrown by |throw| statement.
     if (!exnObj->is<ErrorObject>())
         return true;
 
     // Exceptions thrown while compiling top-level script have no stack.
     RootedObject stackObj(cx, exnObj->as<ErrorObject>().stack());
@@ -8205,17 +8228,17 @@ NewGlobalObject(JSContext* cx, JS::Compa
                 JSPrincipals* principals)
 {
     RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, principals,
                                              JS::DontFireOnNewGlobalHook, options));
     if (!glob)
         return nullptr;
 
     {
-        JSAutoCompartment ac(cx, glob);
+        JSAutoRealm ar(cx, glob);
 
 #ifndef LAZY_STANDARD_CLASSES
         if (!JS_InitStandardClasses(cx, glob))
             return nullptr;
 #endif
 
         bool succeeded;
         if (!JS_SetImmutablePrototype(cx, glob, &succeeded))
@@ -8798,33 +8821,33 @@ Shell(JSContext* cx, OptionParser* op, c
     Maybe<JS::AutoDisableGenerationalGC> noggc;
     if (op->getBoolOption("no-ggc"))
         noggc.emplace(cx);
 
     Maybe<AutoDisableCompactingGC> nocgc;
     if (op->getBoolOption("no-cgc"))
         nocgc.emplace(cx);
 
-    JSAutoRequest ar(cx);
+    JSAutoRequest areq(cx);
 
     if (op->getBoolOption("fuzzing-safe"))
         fuzzingSafe = true;
     else
         fuzzingSafe = (getenv("MOZ_FUZZING_SAFE") && getenv("MOZ_FUZZING_SAFE")[0] != '0');
 
     if (op->getBoolOption("disable-oom-functions"))
         disableOOMFunctions = true;
 
     JS::CompartmentOptions options;
     SetStandardCompartmentOptions(options);
     RootedObject glob(cx, NewGlobalObject(cx, options, nullptr));
     if (!glob)
         return 1;
 
-    JSAutoCompartment ac(cx, glob);
+    JSAutoRealm ar(cx, glob);
 
     ShellContext* sc = GetShellContext(cx);
     int result = EXIT_SUCCESS;
     {
         AutoReportException are(cx);
         if (!ProcessArgs(cx, op) && !sc->quitting)
             result = EXITCODE_RUNTIME_ERROR;
     }
@@ -9293,16 +9316,18 @@ main(int argc, char** argv, char** envp)
         JS_SetGCParameter(cx, JSGC_DYNAMIC_HEAP_GROWTH, 1);
         JS_SetGCParameter(cx, JSGC_DYNAMIC_MARK_SLICE, 1);
         JS_SetGCParameter(cx, JSGC_SLICE_TIME_BUDGET, 10);
     }
 #endif
 
     js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
 
+    JS::SetModuleResolveHook(cx->runtime(), CallModuleResolveHook);
+
     result = Shell(cx, &op, envp);
 
 #ifdef DEBUG
     if (OOM_printAllocationCount)
         printf("OOM max count: %" PRIu64 "\n", js::oom::counter);
 #endif
 
     JS_SetGrayGCRootsTracer(cx, nullptr, nullptr);
--- a/js/src/shell/jsshell.h
+++ b/js/src/shell/jsshell.h
@@ -176,16 +176,17 @@ struct ShellContext
 
     JS::UniqueChars moduleLoadPath;
     UniquePtr<MarkBitObservers> markObservers;
 
     // Off-thread parse state.
     js::Monitor offThreadMonitor;
     Vector<OffThreadJob*, 0, SystemAllocPolicy> offThreadJobs;
 
+    JS::PersistentRootedFunction moduleResolveHook;
 };
 
 extern ShellContext*
 GetShellContext(JSContext* cx);
 
 } /* namespace shell */
 } /* namespace js */
 
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -3192,18 +3192,18 @@ Debugger::trace(JSTracer* trc)
      *
      * (Once we support generator frames properly, we will need
      * weakly-referenced Debugger.Frame objects as well, for suspended generator
      * frames.)
      */
     if (frames.initialized()) {
         for (FrameMap::Range r = frames.all(); !r.empty(); r.popFront()) {
             HeapPtr<DebuggerFrame*>& frameobj = r.front().value();
-            MOZ_ASSERT(MaybeForwarded(frameobj.get())->getPrivate());
             TraceEdge(trc, &frameobj, "live Debugger.Frame");
+            MOZ_ASSERT(frameobj->getPrivate(frameobj->numFixedSlotsMaybeForwarded()));
         }
     }
 
     allocationsLog.trace(trc);
 
     /* Trace the weak map from JSScript instances to Debugger.Script objects. */
     scripts.trace(trc);
 
@@ -9290,17 +9290,17 @@ DebuggerObject::promiseIDGetter(JSContex
 
 /* static */ bool
 DebuggerObject::promiseDependentPromisesGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT_OWNER_PROMISE(cx, argc, vp, "get promiseDependentPromises", args, dbg, refobj);
 
     Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
     {
-        JSAutoCompartment ac(cx, promise);
+        JSAutoRealm ar(cx, promise);
         if (!promise->dependentPromises(cx, &values))
             return false;
     }
     for (size_t i = 0; i < values.length(); i++) {
         if (!dbg->wrapDebuggeeValue(cx, values[i]))
             return false;
     }
     RootedArrayObject promises(cx);
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -100,17 +100,16 @@ class GlobalObject : public NativeObject
         IMPORT_ENTRY_PROTO,
         EXPORT_ENTRY_PROTO,
         REQUESTED_MODULE_PROTO,
         REGEXP_STATICS,
         RUNTIME_CODEGEN_ENABLED,
         DEBUGGERS,
         INTRINSICS,
         FOR_OF_PIC_CHAIN,
-        MODULE_RESOLVE_HOOK,
         WINDOW_PROXY,
 
         /* Total reserved-slot count for global objects. */
         RESERVED_SLOTS
     };
 
     /*
      * The slot count must be in the public API for JSCLASS_GLOBAL_FLAGS, and
@@ -816,29 +815,16 @@ class GlobalObject : public NativeObject
         Value v = getReservedSlot(WINDOW_PROXY);
         MOZ_ASSERT(v.isObject() || v.isUndefined());
         return v.isObject() ? &v.toObject() : nullptr;
     }
     void setWindowProxy(JSObject* windowProxy) {
         setReservedSlot(WINDOW_PROXY, ObjectValue(*windowProxy));
     }
 
-    void setModuleResolveHook(HandleFunction hook) {
-        MOZ_ASSERT(hook);
-        setSlot(MODULE_RESOLVE_HOOK, ObjectValue(*hook));
-    }
-
-    JSFunction* moduleResolveHook() {
-        Value value = getSlotRef(MODULE_RESOLVE_HOOK);
-        if (value.isUndefined())
-            return nullptr;
-
-        return &value.toObject().as<JSFunction>();
-    }
-
     // A class used in place of a prototype during off-thread parsing.
     struct OffThreadPlaceholderObject : public NativeObject
     {
         static const int32_t SlotIndexSlot = 0;
         static const Class class_;
         static OffThreadPlaceholderObject* New(JSContext* cx, unsigned slot);
         inline int32_t getSlotIndex() const;
     };
--- a/js/src/vm/JSObject.cpp
+++ b/js/src/vm/JSObject.cpp
@@ -1147,29 +1147,29 @@ JS_CopyPropertyFrom(JSContext* cx, Handl
     if (desc.setter() && !desc.hasSetterObject())
         return true;
 
     if (copyBehavior == MakeNonConfigurableIntoConfigurable) {
         // Mask off the JSPROP_PERMANENT bit.
         desc.attributesRef() &= ~JSPROP_PERMANENT;
     }
 
-    JSAutoCompartment ac(cx, target);
+    JSAutoRealm ar(cx, target);
     cx->markId(id);
     RootedId wrappedId(cx, id);
     if (!cx->compartment()->wrap(cx, &desc))
         return false;
 
     return DefineProperty(cx, target, wrappedId, desc);
 }
 
 JS_FRIEND_API(bool)
 JS_CopyPropertiesFrom(JSContext* cx, HandleObject target, HandleObject obj)
 {
-    JSAutoCompartment ac(cx, obj);
+    JSAutoRealm ar(cx, obj);
 
     AutoIdVector props(cx);
     if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, &props))
         return false;
 
     for (size_t i = 0; i < props.length(); ++i) {
         if (!JS_CopyPropertyFrom(cx, props[i], target, obj))
             return false;
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -4439,22 +4439,22 @@ JSScript::mayReadFrameArgsDirectly()
 }
 
 void
 JSScript::AutoDelazify::holdScript(JS::HandleFunction fun)
 {
     if (fun) {
         if (fun->compartment()->isSelfHosting) {
             // The self-hosting compartment is shared across runtimes, so we
-            // can't use JSAutoCompartment: it could cause races. Functions in
-            // the self-hosting compartment will never be lazy, so we can safely
+            // can't use JSAutoRealm: it could cause races. Functions in the
+            // self-hosting compartment will never be lazy, so we can safely
             // assume we don't have to delazify.
             script_ = fun->nonLazyScript();
         } else {
-            JSAutoCompartment ac(cx_, fun);
+            JSAutoRealm ar(cx_, fun);
             script_ = JSFunction::getOrCreateScript(cx_, fun);
             if (script_) {
                 oldDoNotRelazify_ = script_->doNotRelazify_;
                 script_->setDoNotRelazify(true);
             }
         }
     }
 }
--- a/js/src/vm/NativeObject-inl.h
+++ b/js/src/vm/NativeObject-inl.h
@@ -28,17 +28,17 @@ NativeObject::numFixedSlotsMaybeForwarde
 {
     return gc::MaybeForwarded(lastProperty())->numFixedSlots();
 }
 
 inline uint8_t*
 NativeObject::fixedData(size_t nslots) const
 {
     MOZ_ASSERT(ClassCanHaveFixedData(getClass()));
-    MOZ_ASSERT(nslots == numFixedSlots() + (hasPrivate() ? 1 : 0));
+    MOZ_ASSERT(nslots == numFixedSlotsMaybeForwarded() + (hasPrivate() ? 1 : 0));
     return reinterpret_cast<uint8_t*>(&fixedSlots()[nslots]);
 }
 
 inline void
 NativeObject::removeLastProperty(JSContext* cx)
 {
     MOZ_ASSERT(canRemoveLastProperty());
     MOZ_ALWAYS_TRUE(setLastProperty(cx, lastProperty()->previous()));
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -297,16 +297,24 @@ js::NativeObject::slotInRange(uint32_t s
 bool
 js::NativeObject::slotIsFixed(uint32_t slot) const
 {
     // We call numFixedSlotsMaybeForwarded() to allow reading slots of
     // associated objects in trace hooks that may be called during a moving GC.
     return slot < numFixedSlotsMaybeForwarded();
 }
 
+bool
+js::NativeObject::isNumFixedSlots(uint32_t nfixed) const
+{
+    // We call numFixedSlotsMaybeForwarded() to allow reading slots of
+    // associated objects in trace hooks that may be called during a moving GC.
+    return nfixed == numFixedSlotsMaybeForwarded();
+}
+
 #endif /* DEBUG */
 
 Shape*
 js::NativeObject::lookup(JSContext* cx, jsid id)
 {
     MOZ_ASSERT(isNative());
     return Shape::search(cx, lastProperty(), id);
 }
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -687,16 +687,21 @@ class NativeObject : public ShapedObject
      * If sentinelAllowed then slot may equal the slot capacity.
      */
     bool slotInRange(uint32_t slot, SentinelAllowed sentinel = SENTINEL_NOT_ALLOWED) const;
 
     /*
      * Check whether a slot is a fixed slot.
      */
     bool slotIsFixed(uint32_t slot) const;
+
+    /*
+     * Check whether the supplied number of fixed slots is correct.
+     */
+    bool isNumFixedSlots(uint32_t nfixed) const;
 #endif
 
     /*
      * Minimum size for dynamically allocated slots in normal Objects.
      * ArrayObjects don't use this limit and can have a lower slot capacity,
      * since they normally don't have a lot of slots.
      */
     static const uint32_t SLOT_CAPACITY_MIN = 8;
@@ -735,18 +740,20 @@ class NativeObject : public ShapedObject
                       "int32_t, too)");
     }
 
     uint32_t numFixedSlots() const {
         return reinterpret_cast<const shadow::Object*>(this)->numFixedSlots();
     }
 
     // Get the number of fixed slots when the shape pointer may have been
-    // forwarded by a moving GC.
-    uint32_t numFixedSlotsMaybeForwarded() const;
+    // forwarded by a moving GC. You need to use this rather that
+    // numFixedSlots() in a trace hook if you access an object that is not the
+    // object being traced, since it may have a stale shape pointer.
+    inline uint32_t numFixedSlotsMaybeForwarded() const;
 
     uint32_t numUsedFixedSlots() const {
         uint32_t nslots = lastProperty()->slotSpan(getClass());
         return Min(nslots, numFixedSlots());
     }
 
     uint32_t slotSpan() const {
         if (inDictionaryMode())
@@ -1406,17 +1413,17 @@ class NativeObject : public ShapedObject
     /* Private data accessors. */
 
     inline void*& privateRef(uint32_t nfixed) const { /* XXX should be private, not protected! */
         /*
          * The private pointer of an object can hold any word sized value.
          * Private pointers are stored immediately after the last fixed slot of
          * the object.
          */
-        MOZ_ASSERT(nfixed == numFixedSlots());
+        MOZ_ASSERT(isNumFixedSlots(nfixed));
         MOZ_ASSERT(hasPrivate());
         HeapSlot* end = &fixedSlots()[nfixed];
         return *reinterpret_cast<void**>(end);
     }
 
     bool hasPrivate() const {
         return getClass()->hasPrivate();
     }
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -169,17 +169,18 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
     parallelParsingEnabled_(true),
     autoWritableJitCodeActive_(false),
     oomCallback(nullptr),
     debuggerMallocSizeOf(ReturnZeroSize),
     lastAnimationTime(0),
     performanceMonitoring_(),
     stackFormat_(parentRuntime ? js::StackFormat::Default
                                : js::StackFormat::SpiderMonkey),
-    wasmInstances(mutexid::WasmRuntimeInstances)
+    wasmInstances(mutexid::WasmRuntimeInstances),
+    moduleResolveHook()
 {
     JS_COUNT_CTOR(JSRuntime);
     liveRuntimesCount++;
 
     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
 
     PodZero(&asmJSCacheOps);
     lcovOutput().init();
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -932,16 +932,19 @@ struct JSRuntime : public js::MallocProv
   public:
     js::RuntimeCaches& caches() { return caches_.ref(); }
 
     // List of all the live wasm::Instances in the runtime. Equal to the union
     // of all instances registered in all JSCompartments. Accessed from watchdog
     // threads for purposes of wasm::InterruptRunningCode().
     js::ExclusiveData<js::wasm::InstanceVector> wasmInstances;
 
+    // The implementation-defined abstract operation HostResolveImportedModule.
+    js::MainThreadData<JS::ModuleResolveHook> moduleResolveHook;
+
   public:
 #if defined(JS_BUILD_BINAST)
     js::BinaryASTSupport& binast() {
         return binast_;
     }
   private:
     js::BinaryASTSupport binast_;
 #endif // defined(JS_BUILD_BINAST)
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -790,23 +790,23 @@ public:
         // Note that obj might be null here, since we're doing this before
         // UnwrapSavedFrame.
         if (obj && cx->compartment() != obj->compartment())
         {
             JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes;
             if (subsumes && subsumes(cx->compartment()->principals(),
                                      obj->compartment()->principals()))
             {
-                ac_.emplace(cx, obj);
+                ar_.emplace(cx, obj);
             }
         }
     }
 
  private:
-    Maybe<JSAutoCompartment> ac_;
+    Maybe<JSAutoRealm> ar_;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 } // namespace
 
 static inline js::SavedFrame*
 UnwrapSavedFrame(JSContext* cx, HandleObject obj, SavedFrameSelfHosted selfHosted,
                  bool& skippedAsync)
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2141,35 +2141,36 @@ intrinsic_NameForTypedArray(JSContext* c
     return true;
 }
 
 static bool
 intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 2);
-    MOZ_ASSERT(args[0].toObject().is<ModuleObject>());
-    MOZ_ASSERT(args[1].isString());
-
-    RootedFunction moduleResolveHook(cx, cx->global()->moduleResolveHook());
+    RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
+    RootedString specifier(cx, args[1].toString());
+
+    JS::ModuleResolveHook moduleResolveHook = cx->runtime()->moduleResolveHook;
     if (!moduleResolveHook) {
         JS_ReportErrorASCII(cx, "Module resolve hook not set");
         return false;
     }
 
-    RootedValue result(cx);
-    if (!JS_CallFunction(cx, nullptr, moduleResolveHook, args, &result))
+    RootedObject result(cx);
+    result = moduleResolveHook(cx, module, specifier);
+    if (!result)
         return false;
 
-    if (!result.isObject() || !result.toObject().is<ModuleObject>()) {
+    if (!result->is<ModuleObject>()) {
         JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
         return false;
     }
 
-    args.rval().set(result);
+    args.rval().setObject(*result);
     return true;
 }
 
 static bool
 intrinsic_CreateImportBinding(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 4);
@@ -2932,17 +2933,17 @@ JSRuntime::initSelfHosting(JSContext* cx
      * parented to this one, so cannot include state in the nursery.
      */
     JS::AutoDisableGenerationalGC disable(cx);
 
     Rooted<GlobalObject*> shg(cx, JSRuntime::createSelfHostingGlobal(cx));
     if (!shg)
         return false;
 
-    JSAutoCompartment ac(cx, shg);
+    JSAutoRealm ar(cx, shg);
 
     /*
      * Set a temporary error reporter printing to stderr because it is too
      * early in the startup process for any other reporter to be registered
      * and we don't want errors in self-hosted code to be silently swallowed.
      *
      * This class also overrides the warning reporter to print warnings to
      * stderr. See selfHosting_WarningReporter.
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1110,17 +1110,17 @@ JSStructuredCloneWriter::parseTransferab
             if (unwrappedObj->as<ArrayBufferObject>().isExternal())
                 return reportDataCloneError(JS_SCERR_TRANSFERABLE);
         }
 
         else  {
             if (!out.buf.callbacks_ || !out.buf.callbacks_->canTransfer)
                 return reportDataCloneError(JS_SCERR_TRANSFERABLE);
 
-            JSAutoCompartment ac(cx, unwrappedObj);
+            JSAutoRealm ar(cx, unwrappedObj);
             if (!out.buf.callbacks_->canTransfer(cx, unwrappedObj, out.buf.closure_))
                 return false;
         }
 
         // No duplicates allowed
         auto p = transferableObjects.lookupForAdd(tObj);
         if (p)
             return reportDataCloneError(JS_SCERR_DUP_TRANSFERABLE);
@@ -1194,17 +1194,17 @@ JSStructuredCloneWriter::checkStack()
  * Int16Array views of the same ArrayBuffer, should the data bytes be
  * byte-swapped when writing or not? The Int8Array requires them to not be
  * swapped; the Int16Array requires that they are.
  */
 bool
 JSStructuredCloneWriter::writeTypedArray(HandleObject obj)
 {
     Rooted<TypedArrayObject*> tarr(context(), &CheckedUnwrap(obj)->as<TypedArrayObject>());
-    JSAutoCompartment ac(context(), tarr);
+    JSAutoRealm ar(context(), tarr);
 
     if (!TypedArrayObject::ensureHasBuffer(context(), tarr))
         return false;
 
     if (!out.writePair(SCTAG_TYPED_ARRAY_OBJECT, tarr->length()))
         return false;
     uint64_t type = tarr->type();
     if (!out.write(type))
@@ -1217,34 +1217,34 @@ JSStructuredCloneWriter::writeTypedArray
 
     return out.write(tarr->byteOffset());
 }
 
 bool
 JSStructuredCloneWriter::writeDataView(HandleObject obj)
 {
     Rooted<DataViewObject*> view(context(), &CheckedUnwrap(obj)->as<DataViewObject>());
-    JSAutoCompartment ac(context(), view);
+    JSAutoRealm ar(context(), view);
 
     if (!out.writePair(SCTAG_DATA_VIEW_OBJECT, view->byteLength()))
         return false;
 
     // Write out the ArrayBuffer tag and contents
     RootedValue val(context(), DataViewObject::bufferValue(view));
     if (!startWrite(val))
         return false;
 
     return out.write(view->byteOffset());
 }
 
 bool
 JSStructuredCloneWriter::writeArrayBuffer(HandleObject obj)
 {
     Rooted<ArrayBufferObject*> buffer(context(), &CheckedUnwrap(obj)->as<ArrayBufferObject>());
-    JSAutoCompartment ac(context(), buffer);
+    JSAutoRealm ar(context(), buffer);
 
     return out.writePair(SCTAG_ARRAY_BUFFER_OBJECT, buffer->byteLength()) &&
            out.writeBytes(buffer->dataPointer(), buffer->byteLength());
 }
 
 bool
 JSStructuredCloneWriter::writeSharedArrayBuffer(HandleObject obj)
 {
@@ -1357,17 +1357,17 @@ JSStructuredCloneWriter::traverseObject(
 bool
 JSStructuredCloneWriter::traverseMap(HandleObject obj)
 {
     Rooted<GCVector<Value>> newEntries(context(), GCVector<Value>(context()));
     {
         // If there is no wrapper, the compartment munging is a no-op.
         RootedObject unwrapped(context(), CheckedUnwrap(obj));
         MOZ_ASSERT(unwrapped);
-        JSAutoCompartment ac(context(), unwrapped);
+        JSAutoRealm ar(context(), unwrapped);
         if (!MapObject::getKeysAndValuesInterleaved(unwrapped, &newEntries))
             return false;
     }
     if (!context()->compartment()->wrap(context(), &newEntries))
         return false;
 
     for (size_t i = newEntries.length(); i > 0; --i) {
         if (!entries.append(newEntries[i - 1]))
@@ -1387,17 +1387,17 @@ JSStructuredCloneWriter::traverseMap(Han
 bool
 JSStructuredCloneWriter::traverseSet(HandleObject obj)
 {
     Rooted<GCVector<Value>> keys(context(), GCVector<Value>(context()));
     {
         // If there is no wrapper, the compartment munging is a no-op.
         RootedObject unwrapped(context(), CheckedUnwrap(obj));
         MOZ_ASSERT(unwrapped);
-        JSAutoCompartment ac(context(), unwrapped);
+        JSAutoRealm ar(context(), unwrapped);
         if (!SetObject::keys(context(), unwrapped, &keys))
             return false;
     }
     if (!context()->compartment()->wrap(context(), &keys))
         return false;
 
     for (size_t i = keys.length(); i > 0; --i) {
         if (!entries.append(keys[i - 1]))
@@ -1682,17 +1682,17 @@ JSStructuredCloneWriter::transferOwnersh
             return false;
 
         if (cls == ESClass::ArrayBuffer) {
             tag = SCTAG_TRANSFER_MAP_ARRAY_BUFFER;
 
             // The current setup of the array buffer inheritance hierarchy doesn't
             // lend itself well to generic manipulation via proxies.
             Rooted<ArrayBufferObject*> arrayBuffer(cx, &CheckedUnwrap(obj)->as<ArrayBufferObject>());
-            JSAutoCompartment ac(cx, arrayBuffer);
+            JSAutoRealm ar(cx, arrayBuffer);
 
             if (arrayBuffer->isDetached()) {
                 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
                 return false;
             }
 
             size_t nbytes = arrayBuffer->byteLength();
 
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -891,17 +891,17 @@ class TypedArrayObjectTemplate : public 
             protoRoot =
                 GlobalObject::getOrCreatePrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()));
             if (!protoRoot)
                 return nullptr;
         }
 
         RootedObject typedArray(cx);
         {
-            JSAutoCompartment ac(cx, unwrappedBuffer);
+            JSAutoRealm ar(cx, unwrappedBuffer);
 
             RootedObject wrappedProto(cx, protoRoot);
             if (!cx->compartment()->wrap(cx, &wrappedProto))
                 return nullptr;
 
             typedArray =
                 makeInstance(cx, unwrappedBuffer, CreateSingleton::No, uint32_t(byteOffset),
                              length, wrappedProto);
@@ -1172,17 +1172,17 @@ TypedArrayObjectTemplate<T>::fromTypedAr
         srcArray = &other->as<TypedArrayObject>();
     } else {
         RootedObject unwrapped(cx, CheckedUnwrap(other));
         if (!unwrapped) {
             ReportAccessDenied(cx);
             return nullptr;
         }
 
-        JSAutoCompartment ac(cx, unwrapped);
+        JSAutoRealm ar(cx, unwrapped);
 
         srcArray = &unwrapped->as<TypedArrayObject>();
 
         // To keep things simpler, we always reify the array buffer for
         // wrapped typed arrays.
         if (!TypedArrayObject::ensureHasBuffer(cx, srcArray))
             return nullptr;
     }
--- a/js/src/wasm/WasmInstance.cpp
+++ b/js/src/wasm/WasmInstance.cpp
@@ -416,18 +416,18 @@ Instance::memCopy(Instance* instance, ui
 
         // Here, we know that |len - 1| cannot underflow.
         typedef CheckedInt<uint32_t> CheckedU32;
         CheckedU32 highest_destOffset = CheckedU32(destByteOffset) + CheckedU32(len - 1);
         CheckedU32 highest_srcOffset = CheckedU32(srcByteOffset) + CheckedU32(len - 1);
 
         if (highest_destOffset.isValid()   &&   // wraparound check
             highest_srcOffset.isValid()    &&   // wraparound check
-            destByteOffset + len <= memLen &&   // range check
-            srcByteOffset + len <= memLen)      // range check
+            highest_destOffset.value() < memLen &&   // range check
+            highest_srcOffset.value() < memLen)      // range check
         {
             memmove(rawBuf + destByteOffset, rawBuf + srcByteOffset, size_t(len));
             return 0;
         }
         // else fall through to failure case
     }
 
     JSContext* cx = TlsContext.get();
@@ -455,17 +455,17 @@ Instance::memFill(Instance* instance, ui
         ArrayBufferObjectMaybeShared& arrBuf = mem->buffer();
         uint8_t* rawBuf = arrBuf.dataPointerEither().unwrap();
 
         // Here, we know that |len - 1| cannot underflow.
         typedef CheckedInt<uint32_t> CheckedU32;
         CheckedU32 highest_offset = CheckedU32(byteOffset) + CheckedU32(len - 1);
 
         if (highest_offset.isValid() &&     // wraparound check
-            byteOffset + len <= memLen)     // range check
+            highest_offset.value() < memLen)     // range check
         {
             memset(rawBuf + byteOffset, int(value), size_t(len));
             return 0;
         }
         // else fall through to failure case
 
     }
 
--- a/js/xpconnect/loader/ChromeScriptLoader.cpp
+++ b/js/xpconnect/loader/ChromeScriptLoader.cpp
@@ -303,17 +303,17 @@ PrecompiledScript::~PrecompiledScript()
 
 void
 PrecompiledScript::ExecuteInGlobal(JSContext* aCx, HandleObject aGlobal,
                                    MutableHandleValue aRval,
                                    ErrorResult& aRv)
 {
     {
         RootedObject targetObj(aCx, JS_FindCompilationScope(aCx, aGlobal));
-        JSAutoCompartment ac(aCx, targetObj);
+        JSAutoRealm ar(aCx, targetObj);
 
         Rooted<JSScript*> script(aCx, mScript);
         if (!JS::CloneAndExecuteScript(aCx, script, aRval)) {
             aRv.NoteJSContextException(aCx);
             return;
         }
     }
 
--- a/js/xpconnect/loader/ScriptPreloader.cpp
+++ b/js/xpconnect/loader/ScriptPreloader.cpp
@@ -962,17 +962,17 @@ ScriptPreloader::MaybeFinishOffThreadDec
         mParsingScripts.clear();
 
         DecodeNextBatch(OFF_THREAD_CHUNK_SIZE);
     });
 
     AutoSafeJSAPI jsapi;
     JSContext* cx = jsapi.cx();
 
-    JSAutoCompartment ac(cx, CompilationScope(cx));
+    JSAutoRealm ar(cx, CompilationScope(cx));
     JS::Rooted<JS::ScriptVector> jsScripts(cx, JS::ScriptVector(cx));
 
     // If this fails, we still need to mark the scripts as finished. Any that
     // weren't successfully compiled in this operation (which should never
     // happen under ordinary circumstances) will be re-decoded on the main
     // thread, and raise the appropriate errors when they're executed.
     //
     // The exception from the off-thread decode operation will be reported when
@@ -1032,17 +1032,17 @@ ScriptPreloader::DecodeNextBatch(size_t 
     }
 
     if (size == 0 && mPendingScripts.isEmpty()) {
         return;
     }
 
     AutoSafeJSAPI jsapi;
     JSContext* cx = jsapi.cx();
-    JSAutoCompartment ac(cx, scope ? scope : CompilationScope(cx));
+    JSAutoRealm ar(cx, scope ? scope : CompilationScope(cx));
 
     JS::CompileOptions options(cx);
     options.setNoScriptRval(true)
            .setSourceIsLazy(true);
 
     if (!JS::CanCompileOffThread(cx, options, size) ||
         !JS::DecodeMultiOffThreadScripts(cx, options, mParsingSources,
                                          OffThreadDecodeCallback,
@@ -1078,17 +1078,17 @@ ScriptPreloader::CachedScript::CachedScr
     // compare against last session's values later.
     mOriginalProcessTypes = mProcessTypes;
     mProcessTypes = {};
 }
 
 bool
 ScriptPreloader::CachedScript::XDREncode(JSContext* cx)
 {
-    JSAutoCompartment ac(cx, mScript);
+    JSAutoRealm ar(cx, mScript);
     JS::RootedScript jsscript(cx, mScript);
 
     mXDRData.construct<JS::TranscodeBuffer>();
 
     JS::TranscodeResult code = JS::EncodeScript(cx, Buffer(), jsscript);
     if (code == JS::TranscodeResult_Ok) {
         mXDRRange.emplace(Buffer().begin(), Buffer().length());
         mSize = Range().length();
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -441,17 +441,17 @@ mozJSComponentLoader::LoadModule(FileLoc
     RootedValue exn(cx);
     rv = ObjectForLocation(info, file, &entry->obj, &entry->thisObjectKey,
                            &entry->location, isCriticalModule, &exn);
     if (NS_FAILED(rv)) {
         // Temporary debugging assertion for bug 1403348:
         if (isCriticalModule && !exn.isUndefined()) {
             AnnotateCrashReport();
 
-            JSAutoCompartment ac(cx, xpc::PrivilegedJunkScope());
+            JSAutoRealm ar(cx, xpc::PrivilegedJunkScope());
             JS_WrapValue(cx, &exn);
 
             nsAutoCString file;
             uint32_t line;
             uint32_t column;
             nsAutoString msg;
             nsContentUtils::ExtractErrorValues(cx, exn, file, &line, &column, msg);
 
@@ -463,17 +463,17 @@ mozJSComponentLoader::LoadModule(FileLoc
         return nullptr;
     }
 
     nsCOMPtr<nsIComponentManager> cm;
     rv = NS_GetComponentManager(getter_AddRefs(cm));
     if (NS_FAILED(rv))
         return nullptr;
 
-    JSAutoCompartment ac(cx, entry->obj);
+    JSAutoRealm ar(cx, entry->obj);
     RootedObject entryObj(cx, entry->obj);
 
     RootedObject NSGetFactoryHolder(cx, ResolveModuleObjectProperty(cx, entryObj, "NSGetFactory"));
     RootedValue NSGetFactory_val(cx);
     if (!NSGetFactoryHolder ||
         !JS_GetProperty(cx, NSGetFactoryHolder, "NSGetFactory", &NSGetFactory_val) ||
         NSGetFactory_val.isUndefined())
     {
@@ -592,17 +592,17 @@ mozJSComponentLoader::CreateLoaderGlobal
                                               options,
                                               &global);
     NS_ENSURE_SUCCESS_VOID(rv);
 
     NS_ENSURE_TRUE_VOID(global);
 
     backstagePass->SetGlobalObject(global);
 
-    JSAutoCompartment ac(aCx, global);
+    JSAutoRealm ar(aCx, global);
     if (!JS_DefineFunctions(aCx, global, gGlobalFun) ||
         !JS_DefineProfilingFunctions(aCx, global)) {
         return;
     }
 
     // Set the location information for the new global, so that tools like
     // about:memory may use that information
     xpc::SetLocationForGlobal(global, aLocation);
@@ -687,17 +687,17 @@ mozJSComponentLoader::PrepareObjectForLo
         CreateLoaderGlobal(aCx, nativePath, &globalObj);
         createdNewGlobal = true;
     }
 
     // |thisObj| is the object we set properties on for a particular .jsm.
     RootedObject thisObj(aCx, globalObj);
     NS_ENSURE_TRUE(thisObj, nullptr);
 
-    JSAutoCompartment ac(aCx, thisObj);
+    JSAutoRealm ar(aCx, thisObj);
 
     if (reuseGlobal) {
         thisObj = js::NewJSMEnvironment(aCx);
         NS_ENSURE_TRUE(thisObj, nullptr);
     }
 
     *aRealFile = false;
 
@@ -796,17 +796,17 @@ mozJSComponentLoader::ObjectForLocation(
     nsresult rv = aInfo.EnsureURI();
     NS_ENSURE_SUCCESS(rv, rv);
     bool reuseGlobal = false;
     RootedObject obj(cx, PrepareObjectForLocation(cx, aComponentFile, aInfo.URI(),
                                                   &reuseGlobal, &realFile));
     NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
     MOZ_ASSERT(JS_IsGlobalObject(obj) == !reuseGlobal);
 
-    JSAutoCompartment ac(cx, obj);
+    JSAutoRealm ar(cx, obj);
 
     RootedScript script(cx);
 
     nsAutoCString nativePath;
     rv = aInfo.URI()->GetSpec(nativePath);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Before compiling the script, first check to see if we have it in
@@ -953,17 +953,17 @@ mozJSComponentLoader::UnloadModules()
 {
     mInitialized = false;
 
     if (mLoaderGlobal) {
         dom::AutoJSAPI jsapi;
         jsapi.Init();
         JSContext* cx = jsapi.cx();
         RootedObject global(cx, mLoaderGlobal);
-        JSAutoCompartment ac(cx, global);
+        JSAutoRealm ar(cx, global);
         MOZ_ASSERT(JS_HasExtensibleLexicalEnvironment(global));
         JS_SetAllNonReservedSlotsToUndefined(cx, JS_ExtensibleLexicalEnvironment(global));
         JS_SetAllNonReservedSlotsToUndefined(cx, global);
         mLoaderGlobal = nullptr;
     }
 
     mInProgressImports.Clear();
     mImports.Clear();
@@ -1006,19 +1006,19 @@ mozJSComponentLoader::ImportInto(const n
             // Not doing so breaks |make package|.
             return ReportOnCallerUTF8(cx, ERROR_SCOPE_OBJ,
                                       PromiseFlatCString(registryLocation).get());
         }
     } else {
         FindTargetObject(cx, &targetObject);
     }
 
-    Maybe<JSAutoCompartment> ac;
+    Maybe<JSAutoRealm> ar;
     if (targetObject) {
-        ac.emplace(cx, targetObject);
+        ar.emplace(cx, targetObject);
     }
 
     RootedObject global(cx);
     nsresult rv = ImportInto(registryLocation, targetObject, cx, &global);
 
     if (global) {
         if (!JS_WrapObject(cx, &global)) {
             NS_ERROR("can't wrap return value");
@@ -1183,17 +1183,17 @@ mozJSComponentLoader::ExtractExports(JSC
     JSCLContextHelper cxhelper(aCx);
 
     // Even though we are calling JS_SetPropertyById on targetObj, we want
     // to ensure that we never run script here, so we use an AutoJSAPI and
     // not an AutoEntryScript.
     dom::AutoJSAPI jsapi;
     jsapi.Init();
     JSContext* cx = jsapi.cx();
-    JSAutoCompartment ac(cx, aMod->obj);
+    JSAutoRealm ar(cx, aMod->obj);
 
     RootedValue symbols(cx);
     {
         RootedObject obj(cx, ResolveModuleObjectProperty(cx, aMod->obj,
                                                          "EXPORTED_SYMBOLS"));
         if (!obj || !JS_GetProperty(cx, obj, "EXPORTED_SYMBOLS", &symbols)) {
             return ReportOnCallerUTF8(cxhelper, ERROR_NOT_PRESENT, aInfo);
         }
--- a/js/xpconnect/loader/mozJSComponentLoader.h
+++ b/js/xpconnect/loader/mozJSComponentLoader.h
@@ -155,17 +155,17 @@ class mozJSComponentLoader final : publi
             Clear();
         }
 
         void Clear() {
             getfactoryobj = nullptr;
 
             if (obj) {
                 mozilla::AutoJSContext cx;
-                JSAutoCompartment ac(cx, obj);
+                JSAutoRealm ar(cx, obj);
 
                 if (JS_HasExtensibleLexicalEnvironment(obj)) {
                     JS_SetAllNonReservedSlotsToUndefined(cx, JS_ExtensibleLexicalEnvironment(obj));
                 }
                 JS_SetAllNonReservedSlotsToUndefined(cx, obj);
                 obj = nullptr;
                 thisObjectKey = nullptr;
             }
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -224,17 +224,17 @@ EvalScript(JSContext* cx,
             MOZ_ASSERT(js::IsJSMEnvironment(loadScope));
             if (!js::ExecuteInJSMEnvironment(cx, script, loadScope, envChain)) {
                 return false;
             }
             retval.setUndefined();
         }
     }
 
-    JSAutoCompartment rac(cx, targetObj);
+    JSAutoRealm rar(cx, targetObj);
     if (!JS_WrapValue(cx, retval)) {
         return false;
     }
 
     if (script && (startupCache || preloadCache)) {
         nsAutoCString cachePath;
         SubscriptCachePath(cx, uri, targetObj, cachePath);
 
@@ -259,17 +259,17 @@ EvalScript(JSContext* cx,
             // disable and reenable an add-on without uninstalling it, leading
             // to cached scripts being held alive, and tied to nuked Sandbox
             // globals. Given the unusual circumstances required to trigger
             // this, it's not a major concern. But it should be kept in mind.
             ScriptPreloader::GetSingleton().NoteScript(uriStr, cachePath, script);
         }
 
         if (startupCache) {
-            JSAutoCompartment ac(cx, script);
+            JSAutoRealm ar(cx, script);
             WriteCachedScript(StartupCache::GetSingleton(), cachePath, cx, script);
         }
     }
 
     return true;
 }
 
 class AsyncScriptLoader : public nsIIncrementalStreamLoaderObserver
@@ -627,17 +627,17 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
 
     // Figure out who's calling us
     JS::AutoFilename filename;
     if (!JS::DescribeScriptedCaller(cx, &filename)) {
         // No scripted frame means we don't know who's calling, bail.
         return NS_ERROR_FAILURE;
     }
 
-    JSAutoCompartment ac(cx, targetObj);
+    JSAutoRealm ar(cx, targetObj);
 
     nsCOMPtr<nsIIOService> serv = do_GetService(NS_IOSERVICE_CONTRACTID);
     if (!serv) {
         ReportError(cx, NS_LITERAL_CSTRING(LOAD_ERROR_NOSERVICE));
         return NS_OK;
     }
 
     NS_LossyConvertUTF16toASCII asciiUrl(url);
--- a/js/xpconnect/src/ExportHelpers.cpp
+++ b/js/xpconnect/src/ExportHelpers.cpp
@@ -206,30 +206,30 @@ public:
  * function returns, |val| is set to the result of the clone.
  */
 bool
 StackScopedClone(JSContext* cx, StackScopedCloneOptions& options,
                  MutableHandleValue val)
 {
     StackScopedCloneData data(cx, &options);
     {
-        // For parsing val we have to enter its compartment.
+        // For parsing val we have to enter its realm.
         // (unless it's a primitive)
-        Maybe<JSAutoCompartment> ac;
+        Maybe<JSAutoRealm> ar;
         if (val.isObject()) {
-            ac.emplace(cx, &val.toObject());
+            ar.emplace(cx, &val.toObject());
         } else if (val.isString() && !JS_WrapValue(cx, val)) {
             return false;
         }
 
         if (!data.Write(cx, val))
             return false;
     }
 
-    // Now recreate the clones in the target compartment.
+    // Now recreate the clones in the target realm.
     if (!data.Read(cx, val))
         return false;
 
     // Deep-freeze if requested.
     if (options.deepFreeze && val.isObject()) {
         RootedObject obj(cx, &val.toObject());
         if (!JS_DeepFreezeObject(cx, obj))
             return false;
@@ -295,17 +295,17 @@ FunctionForwarder(JSContext* cx, unsigne
             return false;
         thisVal.setObject(*thisObject);
     }
 
     {
         // We manually implement the contents of CrossCompartmentWrapper::call
         // here, because certain function wrappers (notably content->nsEP) are
         // not callable.
-        JSAutoCompartment ac(cx, unwrappedFun);
+        JSAutoRealm ar(cx, unwrappedFun);
         if (!CheckSameOriginArg(cx, options, thisVal) || !JS_WrapValue(cx, &thisVal))
             return false;
 
         for (size_t n = 0;  n < args.length(); ++n) {
             if (!CheckSameOriginArg(cx, options, args[n]) || !JS_WrapValue(cx, args[n]))
                 return false;
         }
 
@@ -394,18 +394,18 @@ ExportFunction(JSContext* cx, HandleValu
 
     if (js::IsScriptedProxy(targetScope)) {
         JS_ReportErrorASCII(cx, "Defining property on proxy object is not allowed");
         return false;
     }
 
     {
         // We need to operate in the target scope from here on, let's enter
-        // its compartment.
-        JSAutoCompartment ac(cx, targetScope);
+        // its realm.
+        JSAutoRealm ar(cx, targetScope);
 
         // Unwrapping to see if we have a callable.
         funObj = UncheckedUnwrap(funObj);
         if (!JS::IsCallable(funObj)) {
             JS_ReportErrorASCII(cx, "First argument must be a function");
             return false;
         }
 
@@ -478,17 +478,17 @@ CreateObjectIn(JSContext* cx, HandleValu
 
     if (define && js::IsScriptedProxy(scope)) {
         JS_ReportErrorASCII(cx, "Defining property on proxy object is not allowed");
         return false;
     }
 
     RootedObject obj(cx);
     {
-        JSAutoCompartment ac(cx, scope);
+        JSAutoRealm ar(cx, scope);
         JS_MarkCrossZoneId(cx, options.defineAs);
 
         obj = JS_NewPlainObject(cx);
         if (!obj)
             return false;
 
         if (define) {
             if (!JS_DefinePropertyById(cx, scope, options.defineAs, obj,
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -190,17 +190,17 @@ SandboxImport(JSContext* cx, unsigned ar
             return false;
     } else {
         // NB: funobj must only be used to get the JSFunction out.
         RootedObject funobj(cx, &args[0].toObject());
         if (js::IsProxy(funobj)) {
             funobj = XPCWrapper::UnsafeUnwrapSecurityWrapper(funobj);
         }
 
-        JSAutoCompartment ac(cx, funobj);
+        JSAutoRealm ar(cx, funobj);
 
         RootedValue funval(cx, ObjectValue(*funobj));
         JSFunction* fun = JS_ValueToFunction(cx, funval);
         if (!fun) {
             XPCThrower::Throw(NS_ERROR_INVALID_ARG, cx);
             return false;
         }
 
@@ -1065,17 +1065,17 @@ xpc::CreateSandboxObject(JSContext* cx, 
     // same-origin Xrays for chrome->chrome access seems a bit superfluous.
     // Arguably we should just flip the default for chrome and still honor the
     // flag, but such a change would break code in subtle ways for minimal
     // benefit. So we just switch it off here.
     priv->wantXrays =
       AccessCheck::isChrome(sandbox) ? false : options.wantXrays;
 
     {
-        JSAutoCompartment ac(cx, sandbox);
+        JSAutoRealm ar(cx, sandbox);
 
         nsCOMPtr<nsIScriptObjectPrincipal> sbp =
             new SandboxPrivate(principal, sandbox);
 
         // Pass on ownership of sbp to |sandbox|.
         JS_SetPrivate(sandbox, sbp.forget().take());
 
         // Ensure |Object.prototype| is instantiated before prototype-
@@ -1151,17 +1151,17 @@ xpc::CreateSandboxObject(JSContext* cx, 
         return NS_ERROR_UNEXPECTED;
 
     // Set the location information for the new global, so that tools like
     // about:memory may use that information
     xpc::SetLocationForGlobal(sandbox, options.sandboxName);
 
     xpc::SetSandboxMetadata(cx, sandbox, options.metadata);
 
-    JSAutoCompartment ac(cx, sandbox);
+    JSAutoRealm ar(cx, sandbox);
     JS_FireOnNewGlobalObject(cx, sandbox);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_utils_Sandbox::Call(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
                                     JSObject* objArg, const CallArgs& args, bool* _retval)
@@ -1786,17 +1786,17 @@ xpc::EvalInSandbox(JSContext* cx, Handle
     RootedValue v(cx, UndefinedValue());
     RootedValue exn(cx, UndefinedValue());
     bool ok = true;
     {
         // We're about to evaluate script, so make an AutoEntryScript.
         // This is clearly Gecko-specific and not in any spec.
         mozilla::dom::AutoEntryScript aes(priv, "XPConnect sandbox evaluation");
         JSContext* sandcx = aes.cx();
-        JSAutoCompartment ac(sandcx, sandbox);
+        JSAutoRealm 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);
 
         // If the sandbox threw an exception, grab it off the context.
@@ -1839,17 +1839,17 @@ xpc::EvalInSandbox(JSContext* cx, Handle
 nsresult
 xpc::GetSandboxMetadata(JSContext* cx, HandleObject sandbox, MutableHandleValue rval)
 {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(IsSandbox(sandbox));
 
     RootedValue metadata(cx);
     {
-      JSAutoCompartment ac(cx, sandbox);
+      JSAutoRealm ar(cx, sandbox);
       metadata = JS_GetReservedSlot(sandbox, XPCONNECT_SANDBOX_CLASS_METADATA_SLOT);
     }
 
     if (!JS_WrapValue(cx, &metadata))
         return NS_ERROR_UNEXPECTED;
 
     rval.set(metadata);
     return NS_OK;
@@ -1858,16 +1858,16 @@ xpc::GetSandboxMetadata(JSContext* cx, H
 nsresult
 xpc::SetSandboxMetadata(JSContext* cx, HandleObject sandbox, HandleValue metadataArg)
 {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(IsSandbox(sandbox));
 
     RootedValue metadata(cx);
 
-    JSAutoCompartment ac(cx, sandbox);
+    JSAutoRealm ar(cx, sandbox);
     if (!JS_StructuredClone(cx, metadataArg, &metadata, nullptr, nullptr))
         return NS_ERROR_UNEXPECTED;
 
     JS_SetReservedSlot(sandbox, XPCONNECT_SANDBOX_CLASS_METADATA_SLOT, metadata);
 
     return NS_OK;
 }
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2450,17 +2450,17 @@ nsXPCComponents_Utils::GetGlobalForObjec
     // Wrappers are parented to their the global in their home compartment. But
     // when getting the global for a cross-compartment wrapper, we really want
     // a wrapper for the foreign global. So we need to unwrap before getting the
     // parent, enter the compartment for the duration of the call, and wrap the
     // result.
     Rooted<JSObject*> obj(cx, &object.toObject());
     obj = js::UncheckedUnwrap(obj);
     {
-        JSAutoCompartment ac(cx, obj);
+        JSAutoRealm ar(cx, obj);
         obj = JS_GetGlobalForObject(cx, obj);
     }
 
     if (!JS_WrapObject(cx, &obj))
         return NS_ERROR_FAILURE;
 
     // Get the WindowProxy if necessary.
     obj = js::ToWindowProxyIfWindow(obj);
@@ -2519,17 +2519,17 @@ nsXPCComponents_Utils::MakeObjectPropsNo
     if (!cx)
         return NS_ERROR_FAILURE;
 
     // first argument must be an object
     if (vobj.isPrimitive())
         return NS_ERROR_XPC_BAD_CONVERT_JS;
 
     RootedObject obj(cx, js::UncheckedUnwrap(&vobj.toObject()));
-    JSAutoCompartment ac(cx, obj);
+    JSAutoRealm ar(cx, obj);
     Rooted<IdVector> ida(cx, IdVector(cx));
     if (!JS_Enumerate(cx, obj, &ida))
         return NS_ERROR_FAILURE;
 
     RootedId id(cx);
     RootedValue v(cx);
     for (size_t i = 0; i < ida.length(); ++i) {
         id = ida[i];
@@ -2649,23 +2649,23 @@ nsXPCComponents_Utils::ForcePermissiveCO
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::Dispatch(HandleValue runnableArg, HandleValue scope,
                                 JSContext* cx)
 {
     RootedValue runnable(cx, runnableArg);
-    // Enter the given compartment, if any, and rewrap runnable.
-    Maybe<JSAutoCompartment> ac;
+    // Enter the given realm, if any, and rewrap runnable.
+    Maybe<JSAutoRealm> ar;
     if (scope.isObject()) {
         JSObject* scopeObj = js::UncheckedUnwrap(&scope.toObject());
         if (!scopeObj)
             return NS_ERROR_FAILURE;
-        ac.emplace(cx, scopeObj);
+        ar.emplace(cx, scopeObj);
         if (!JS_WrapValue(cx, &runnable))
             return NS_ERROR_FAILURE;
     }
 
     // Get an XPCWrappedJS for |runnable|.
     if (!runnable.isObject())
         return NS_ERROR_INVALID_ARG;
 
@@ -2891,17 +2891,17 @@ NS_IMETHODIMP
 nsXPCComponents_Utils::GenerateXPCWrappedJS(HandleValue aObj, HandleValue aScope,
                                             JSContext* aCx, nsISupports** aOut)
 {
     if (!aObj.isObject())
         return NS_ERROR_INVALID_ARG;
     RootedObject obj(aCx, &aObj.toObject());
     RootedObject scope(aCx, aScope.isObject() ? js::UncheckedUnwrap(&aScope.toObject())
                                               : CurrentGlobalOrNull(aCx));
-    JSAutoCompartment ac(aCx, scope);
+    JSAutoRealm ar(aCx, scope);
     if (!JS_WrapObject(aCx, &obj))
         return NS_ERROR_FAILURE;
 
     RefPtr<WrappedJSHolder> holder = new WrappedJSHolder();
     nsresult rv = nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsISupports),
                                                getter_AddRefs(holder->mWrappedJS));
     holder.forget(aOut);
     return rv;
@@ -2959,17 +2959,17 @@ xpc::CloneInto(JSContext* aCx, HandleVal
 
     RootedObject optionsObject(aCx, aOptions.isObject() ? &aOptions.toObject()
                                                         : nullptr);
     StackScopedCloneOptions options(aCx, optionsObject);
     if (aOptions.isObject() && !options.Parse())
         return false;
 
     {
-        JSAutoCompartment ac(aCx, scope);
+        JSAutoRealm ar(aCx, scope);
         aCloned.set(aValue);
         if (!StackScopedClone(aCx, options, aCloned))
             return false;
     }
 
     return JS_WrapValue(aCx, aCloned);
 }
 
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -952,17 +952,17 @@ XPCConvert::JSObject2NativeInterface(voi
                                      nsISupports* aOuter,
                                      nsresult* pErr)
 {
     MOZ_ASSERT(dest, "bad param");
     MOZ_ASSERT(src, "bad param");
     MOZ_ASSERT(iid, "bad param");
 
     AutoJSContext cx;
-    JSAutoCompartment ac(cx, src);
+    JSAutoRealm ar(cx, src);
 
     *dest = nullptr;
      if (pErr)
         *pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
 
     nsISupports* iface;
 
     if (!aOuter) {
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -537,17 +537,17 @@ XPCShellInterruptCallback(JSContext* cx)
 {
     MOZ_ASSERT(sScriptedInterruptCallback->initialized());
     RootedValue callback(cx, *sScriptedInterruptCallback);
 
     // If no interrupt callback was set by script, no-op.
     if (callback.isUndefined())
         return true;
 
-    JSAutoCompartment ac(cx, &callback.toObject());
+    JSAutoRealm ar(cx, &callback.toObject());
     RootedValue rv(cx);
     if (!JS_CallFunctionValue(cx, nullptr, callback, JS::HandleValueArray::empty(), &rv) ||
         !rv.isBoolean())
     {
         NS_WARNING("Scripted interrupt callback failed! Terminating script.");
         JS_ClearPendingException(cx);
         return false;
     }
@@ -1334,17 +1334,17 @@ XRE_XPCShellMain(int argc, char** argv, 
 
             // Even if we're building in a configuration where source is
             // discarded, there's no reason to do that on XPCShell, and doing so
             // might break various automation scripts.
             JS::CompartmentBehaviorsRef(glob).setDiscardSource(false);
 
             backstagePass->SetGlobalObject(glob);
 
-            JSAutoCompartment ac(cx, glob);
+            JSAutoRealm ar(cx, glob);
 
             if (!JS_InitReflectParse(cx, glob)) {
                 return 1;
             }
 
             if (!JS_DefineFunctions(cx, glob, glob_functions) ||
                 !JS_DefineProfilingFunctions(cx, glob)) {
                 return 1;
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -41,17 +41,17 @@ bool AutoScriptEvaluate::StartEvaluating
     MOZ_ASSERT(!mEvaluated, "AutoScriptEvaluate::Evaluate should only be called once");
 
     if (!mJSContext)
         return true;
 
     mEvaluated = true;
 
     JS_BeginRequest(mJSContext);
-    mAutoCompartment.emplace(mJSContext, scope);
+    mAutoRealm.emplace(mJSContext, scope);
 
     // Saving the exception state keeps us from interfering with another script
     // that may also be running on this context.  This occurred first with the
     // js debugger, as described in
     // http://bugzilla.mozilla.org/show_bug.cgi?id=88130 but presumably could
     // show up in any situation where a script calls into a wrapped js component
     // on the same context, while the context has a nonzero exception state.
     mState.emplace(mJSContext);
@@ -443,17 +443,17 @@ public:
 };
 
 NS_IMPL_ISUPPORTS(WrappedJSNamed, nsINamed)
 
 nsCString
 GetFunctionName(JSContext* cx, HandleObject obj)
 {
     RootedObject inner(cx, js::UncheckedUnwrap(obj));
-    JSAutoCompartment ac(cx, inner);
+    JSAutoRealm ar(cx, inner);
 
     RootedFunction fun(cx, JS_GetObjectFunction(inner));
     if (!fun) {
         // If the object isn't a function, it's likely that it has a single
         // function property (for things like nsITimerCallback). In this case,
         // return the name of that function property.
 
         Rooted<IdVector> idArray(cx, IdVector(cx));
@@ -963,17 +963,17 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWra
         NS_WARNING(str);
         return CheckForException(ccx, aes, name, GetInterfaceName());
     }
 
     RootedValue fval(cx);
     RootedObject obj(cx, wrapper->GetJSObject());
     RootedObject thisObj(cx, obj);
 
-    JSAutoCompartment ac(cx, obj);
+    JSAutoRealm ar(cx, obj);
 
     AutoValueVector args(cx);
     AutoScriptEvaluate scriptEval(cx);
 
     XPCJSContext* xpccx = ccx.GetContext();
     AutoSavePendingResult apr(xpccx);
 
     // XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -181,19 +181,19 @@ XPCWrappedNative::WrapNewGlobal(xpcObjec
     aOptions.creationOptions().setTrace(XPCWrappedNative::Trace);
     if (xpc::SharedMemoryEnabled())
         aOptions.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
     RootedObject global(cx, xpc::CreateGlobalObject(cx, clasp, principal, aOptions));
     if (!global)
         return NS_ERROR_FAILURE;
     XPCWrappedNativeScope* scope = RealmPrivate::Get(global)->scope;
 
-    // Immediately enter the global's compartment, so that everything else we
+    // Immediately enter the global's realm, so that everything else we
     // create ends up there.
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     // If requested, initialize the standard classes on the global.
     if (initStandardClasses && ! JS_InitStandardClasses(cx, global))
         return NS_ERROR_FAILURE;
 
     // Make a proto.
     XPCWrappedNativeProto* proto =
         XPCWrappedNativeProto::GetNewOrUsed(scope,
@@ -337,33 +337,33 @@ XPCWrappedNative::GetNewOrUsed(xpcObject
     // described by the nsIClassInfo, not for the class info object
     // itself.
     if (!isClassInfoSingleton)
         GatherScriptable(identity, info, getter_AddRefs(scrProto),
                          getter_AddRefs(scrWrapper));
 
     RootedObject parent(cx, Scope->GetGlobalJSObject());
 
-    mozilla::Maybe<JSAutoCompartment> ac;
+    mozilla::Maybe<JSAutoRealm> ar;
 
     if (scrWrapper && scrWrapper->WantPreCreate()) {
         RootedObject plannedParent(cx, parent);
         nsresult rv =
             scrWrapper->PreCreate(identity, cx, parent, parent.address());
         if (NS_FAILED(rv))
             return rv;
         rv = NS_OK;
 
         MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(parent),
                    "Xray wrapper being used to parent XPCWrappedNative?");
 
         MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(parent) == parent,
                    "Non-global being used to parent XPCWrappedNative?");
 
-        ac.emplace(static_cast<JSContext*>(cx), parent);
+        ar.emplace(static_cast<JSContext*>(cx), parent);
 
         if (parent != plannedParent) {
             XPCWrappedNativeScope* betterScope = ObjectScope(parent);
             MOZ_ASSERT(betterScope != Scope,
                        "How can we have the same scope for two different globals?");
             return GetNewOrUsed(helper, betterScope, Interface, resultWrapper);
         }
 
@@ -383,17 +383,17 @@ XPCWrappedNative::GetNewOrUsed(xpcObject
             if (wrapper->FindTearOff(Interface, false, &rv)) {
                 MOZ_ASSERT(NS_FAILED(rv), "returning NS_OK on failure");
                 return rv;
             }
             wrapper.forget(resultWrapper);
             return NS_OK;
         }
     } else {
-        ac.emplace(static_cast<JSContext*>(cx), parent);
+        ar.emplace(static_cast<JSContext*>(cx), parent);
     }
 
     AutoMarkingWrappedNativeProtoPtr proto(cx);
 
     // If there is ClassInfo (and we are not building a wrapper for the
     // nsIClassInfo interface) then we use a wrapper that needs a prototype.
 
     // Note that the security check happens inside FindTearOff - after the
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -152,17 +152,17 @@ GetDoubleWrappedJSObject(XPCCallContext&
     nsCOMPtr<nsIXPConnectWrappedJS>
         underware = do_QueryInterface(wrapper->GetIdentityObject());
     if (underware) {
         RootedObject mainObj(ccx, underware->GetJSObject());
         if (mainObj) {
             RootedId id(ccx, ccx.GetContext()->
                             GetStringID(XPCJSContext::IDX_WRAPPED_JSOBJECT));
 
-            JSAutoCompartment ac(ccx, mainObj);
+            JSAutoRealm ar(ccx, mainObj);
 
             RootedValue val(ccx);
             if (JS_GetPropertyById(ccx, mainObj, id, &val) &&
                 !val.isPrimitive()) {
                 obj = val.toObjectOrNull();
             }
         }
     }
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -286,17 +286,17 @@ XPCWrappedNativeScope::AllowContentXBLSc
     return mAllowContentXBLScope;
 }
 
 namespace xpc {
 JSObject*
 GetXBLScope(JSContext* cx, JSObject* contentScopeArg)
 {
     JS::RootedObject contentScope(cx, contentScopeArg);
-    JSAutoCompartment ac(cx, contentScope);
+    JSAutoRealm ar(cx, contentScope);
     XPCWrappedNativeScope* nativeScope = RealmPrivate::Get(contentScope)->scope;
 
     RootedObject scope(cx, nativeScope->EnsureContentXBLScope(cx));
     NS_ENSURE_TRUE(scope, nullptr); // See bug 858642.
 
     scope = js::UncheckedUnwrap(scope);
     JS::ExposeObjectToActiveJS(scope);
     return scope;
--- a/js/xpconnect/src/XPCWrapper.cpp
+++ b/js/xpconnect/src/XPCWrapper.cpp
@@ -62,17 +62,17 @@ XrayWrapperConstructor(JSContext* cx, un
   return JS_WrapValue(cx, args.rval());
 }
 // static
 bool
 AttachNewConstructorObject(JSContext* aCx, JS::HandleObject aGlobalObject)
 {
   // Pushing a JSContext calls ActivateDebugger which calls this function, so
   // we can't use an AutoJSContext here until JSD is gone.
-  JSAutoCompartment ac(aCx, aGlobalObject);
+  JSAutoRealm ar(aCx, aGlobalObject);
   JSFunction* xpcnativewrapper =
     JS_DefineFunction(aCx, aGlobalObject, "XPCNativeWrapper",
                       XrayWrapperConstructor, 1,
                       JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_CONSTRUCTOR);
   if (!xpcnativewrapper) {
     return false;
   }
   JS::RootedObject obj(aCx, JS_GetFunctionObject(xpcnativewrapper));
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -441,17 +441,17 @@ CreateGlobalObject(JSContext* cx, const 
     MOZ_RELEASE_ASSERT(principal != nsContentUtils::GetNullSubjectPrincipal(),
                        "The null subject principal is getting inherited - fix that!");
 
     RootedObject global(cx,
                         JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal),
                                            JS::DontFireOnNewGlobalHook, aOptions));
     if (!global)
         return nullptr;
-    JSAutoCompartment ac(cx, global);
+    JSAutoRealm ar(cx, global);
 
     // The constructor automatically attaches the scope to the compartment private
     // of |global|.
     (void) new XPCWrappedNativeScope(cx, global);
 
     if (clasp->flags & JSCLASS_DOM_GLOBAL) {
 #ifdef DEBUG
         // Verify that the right trace hook is called. Note that this doesn't
@@ -504,19 +504,19 @@ InitGlobalObjectOptions(JS::CompartmentO
         if (isSystem)
             aOptions.behaviors().extraWarningsOverride().set(true);
     }
 }
 
 bool
 InitGlobalObject(JSContext* aJSContext, JS::Handle<JSObject*> aGlobal, uint32_t aFlags)
 {
-    // Immediately enter the global's compartment so that everything we create
+    // Immediately enter the global's realm so that everything we create
     // ends up there.
-    JSAutoCompartment ac(aJSContext, aGlobal);
+    JSAutoRealm ar(aJSContext, aGlobal);
 
     // Stuff coming through this path always ends up as a DOM global.
     MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL);
 
     if (!(aFlags & xpc::OMIT_COMPONENTS_OBJECT)) {
         // XPCCallContext gives us an active request needed to save/restore.
         if (!RealmPrivate::Get(aGlobal)->scope->AttachComponentsObject(aJSContext) ||
             !XPCNativeWrapper::AttachNewConstructorObject(aJSContext, aGlobal)) {
@@ -579,17 +579,17 @@ static nsresult
 NativeInterface2JSObject(HandleObject aScope,
                          nsISupports* aCOMObj,
                          nsWrapperCache* aCache,
                          const nsIID * aIID,
                          bool aAllowWrapping,
                          MutableHandleValue aVal)
 {
     AutoJSContext cx;
-    JSAutoCompartment ac(cx, aScope);
+    JSAutoRealm ar(cx, aScope);
 
     nsresult rv;
     xpcObjectHelper helper(aCOMObj, aCache);
     if (!XPCConvert::NativeInterface2JSObject(aVal, helper, aIID, aAllowWrapping, &rv))
         return rv;
 
     MOZ_ASSERT(aAllowWrapping || !xpc::WrapperFactory::IsXrayWrapper(&aVal.toObject()),
                "Shouldn't be returning a xray wrapper here");
@@ -648,17 +648,17 @@ nsXPConnect::WrapJS(JSContext * aJSConte
 {
     MOZ_ASSERT(aJSContext, "bad param");
     MOZ_ASSERT(aJSObjArg, "bad param");
     MOZ_ASSERT(result, "bad param");
 
     *result = nullptr;
 
     RootedObject aJSObj(aJSContext, aJSObjArg);
-    JSAutoCompartment ac(aJSContext, aJSObj);
+    JSAutoRealm ar(aJSContext, aJSObj);
 
     nsresult rv = NS_ERROR_UNEXPECTED;
     if (!XPCConvert::JSObject2NativeInterface(result, aJSObj,
                                               &aIID, nullptr, &rv))
         return rv;
     return NS_OK;
 }
 
@@ -783,17 +783,17 @@ nsXPConnect::EvalInSandboxObject(const n
 
 NS_IMETHODIMP
 nsXPConnect::GetWrappedNativePrototype(JSContext* aJSContext,
                                        JSObject* aScopeArg,
                                        nsIClassInfo* aClassInfo,
                                        JSObject** aRetVal)
 {
     RootedObject aScope(aJSContext, aScopeArg);
-    JSAutoCompartment ac(aJSContext, aScope);
+    JSAutoRealm ar(aJSContext, aScope);
 
     XPCWrappedNativeScope* scope = ObjectScope(aScope);
     if (!scope)
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     nsCOMPtr<nsIXPCScriptable> scrProto =
         XPCWrappedNative::GatherProtoScriptable(aClassInfo);
 
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2242,17 +2242,17 @@ public:
     /**
      * Does the post script evaluation.
      */
     ~AutoScriptEvaluate();
 private:
     JSContext* mJSContext;
     mozilla::Maybe<JS::AutoSaveExceptionState> mState;
     bool mEvaluated;
-    mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
+    mozilla::Maybe<JSAutoRealm> mAutoRealm;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
     // No copying or assignment allowed
     AutoScriptEvaluate(const AutoScriptEvaluate&) = delete;
     AutoScriptEvaluate & operator =(const AutoScriptEvaluate&) = delete;
 };
 
 /***************************************************************************/
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -68,17 +68,17 @@ WrapperFactory::GetXrayWaiver(HandleObje
 JSObject*
 WrapperFactory::CreateXrayWaiver(JSContext* cx, HandleObject obj)
 {
     // The caller is required to have already done a lookup.
     // NB: This implictly performs the assertions of GetXrayWaiver.
     MOZ_ASSERT(!GetXrayWaiver(obj));
     XPCWrappedNativeScope* scope = ObjectScope(obj);
 
-    JSAutoCompartment ac(cx, obj);
+    JSAutoRealm ar(cx, obj);
     JSObject* waiver = Wrapper::New(cx, obj, &XrayWaiver);
     if (!waiver)
         return nullptr;
 
     // Add the new waiver to the map. It's important that we only ever have
     // one waiver for the lifetime of the target object.
     if (!scope->mWaiverWrapperMap) {
         scope->mWaiverWrapperMap =
@@ -223,17 +223,17 @@ WrapperFactory::PrepareForWrapping(JSCon
     // between scopes so for those we also want to return the wrapper. So...
     if (!IS_WN_REFLECTOR(obj) || JS_IsGlobalObject(obj)) {
         retObj.set(waive ? WaiveXray(cx, obj) : obj);
         return;
     }
 
     XPCWrappedNative* wn = XPCWrappedNative::Get(obj);
 
-    JSAutoCompartment ac(cx, obj);
+    JSAutoRealm ar(cx, obj);
     XPCCallContext ccx(cx, obj);
     RootedObject wrapScope(cx, scope);
 
     {
         if (ccx.GetScriptable() && ccx.GetScriptable()->WantPreCreate()) {
             // We have a precreate hook. This object might enforce that we only
             // ever create JS object for it.
 
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -320,17 +320,17 @@ ReportWrapperDenial(JSContext* cx, Handl
 bool JSXrayTraits::getOwnPropertyFromWrapperIfSafe(JSContext* cx,
                                                    HandleObject wrapper,
                                                    HandleId id,
                                                    MutableHandle<PropertyDescriptor> outDesc)
 {
     MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
     RootedObject target(cx, getTargetObject(wrapper));
     {
-        JSAutoCompartment ac(cx, target);
+        JSAutoRealm ar(cx, target);
         JS_MarkCrossZoneId(cx, id);
         if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, outDesc))
             return false;
     }
     return JS_WrapPropertyDescriptor(cx, outDesc);
 }
 
 bool JSXrayTraits::getOwnPropertyFromTargetIfSafe(JSContext* cx,
@@ -351,52 +351,52 @@ bool JSXrayTraits::getOwnPropertyFromTar
         return false;
 
     // If the property doesn't exist at all, we're done.
     if (!desc.object())
         return true;
 
     // Disallow accessor properties.
     if (desc.hasGetterOrSetter()) {
-        JSAutoCompartment ac(cx, wrapper);
+        JSAutoRealm ar(cx, wrapper);
         JS_MarkCrossZoneId(cx, id);
         return ReportWrapperDenial(cx, id, WrapperDenialForXray, "property has accessor");
     }
 
     // Apply extra scrutiny to objects.
     if (desc.value().isObject()) {
         RootedObject propObj(cx, js::UncheckedUnwrap(&desc.value().toObject()));
-        JSAutoCompartment ac(cx, propObj);
+        JSAutoRealm ar(cx, propObj);
 
         // Disallow non-subsumed objects.
         if (!AccessCheck::subsumes(target, propObj)) {
-            JSAutoCompartment ac(cx, wrapper);
+            JSAutoRealm ar(cx, wrapper);
             JS_MarkCrossZoneId(cx, id);
             return ReportWrapperDenial(cx, id, WrapperDenialForXray, "value not same-origin with target");
         }
 
         // Disallow non-Xrayable objects.
         XrayType xrayType = GetXrayType(propObj);
         if (xrayType == NotXray || xrayType == XrayForOpaqueObject) {
-            JSAutoCompartment ac(cx, wrapper);
+            JSAutoRealm ar(cx, wrapper);
             JS_MarkCrossZoneId(cx, id);
             return ReportWrapperDenial(cx, id, WrapperDenialForXray, "value not Xrayable");
         }
 
         // Disallow callables.
         if (JS::IsCallable(propObj)) {
-            JSAutoCompartment ac(cx, wrapper);
+            JSAutoRealm ar(cx, wrapper);
             JS_MarkCrossZoneId(cx, id);
             return ReportWrapperDenial(cx, id, WrapperDenialForXray, "value is callable");
         }
     }
 
     // Disallow any property that shadows something on its (Xrayed)
     // prototype chain.
-    JSAutoCompartment ac2(cx, wrapper);
+    JSAutoRealm ar2(cx, wrapper);
     JS_MarkCrossZoneId(cx, id);
     RootedObject proto(cx);
     bool foundOnProto = false;
     if (!JS_GetPrototype(cx, wrapper, &proto) ||
         (proto && !JS_HasPropertyById(cx, proto, id, &foundOnProto)))
     {
         return false;
     }
@@ -564,17 +564,17 @@ JSXrayTraits::resolveOwnProperty(JSConte
         }
         if (IsTypedArrayKey(key)) {
             if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
                 // WebExtensions can't use cloneInto(), so we just let them do
                 // the slow thing to maximize compatibility.
                 if (CompartmentPrivate::Get(CurrentGlobalOrNull(cx))->isWebExtensionContentScript) {
                     Rooted<PropertyDescriptor> innerDesc(cx);
                     {
-                        JSAutoCompartment ac(cx, target);
+                        JSAutoRealm ar(cx, target);
                         JS_MarkCrossZoneId(cx, id);
                         if (!JS_GetOwnPropertyDescriptorById(cx, target, id, &innerDesc))
                             return false;
                     }
                     if (innerDesc.isDataDescriptor() && innerDesc.value().isNumber()) {
                         desc.setValue(innerDesc.value());
                         desc.object().set(wrapper);
                     }
@@ -602,17 +602,17 @@ JSXrayTraits::resolveOwnProperty(JSConte
                 // 'prototype' property.
                 JSProtoKey standardConstructor = constructorFor(holder);
                 if (standardConstructor != JSProto_Null) {
                     // Handle the 'prototype' property to make
                     // xrayedGlobal.StandardClass.prototype work.
                     if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_PROTOTYPE)) {
                         RootedObject standardProto(cx);
                         {
-                            JSAutoCompartment ac(cx, target);
+                            JSAutoRealm ar(cx, target);
                             if (!JS_GetClassPrototype(cx, standardConstructor, &standardProto))
                                 return false;
                             MOZ_ASSERT(standardProto);
                         }
 
                         if (!JS_WrapObject(cx, &standardProto))
                             return false;
                         FillPropertyDescriptor(desc, wrapper, JSPROP_PERMANENT | JSPROP_READONLY,
@@ -672,17 +672,17 @@ JSXrayTraits::resolveOwnProperty(JSConte
         // The rest of this function applies only to prototypes.
         return true;
     }
 
     // Handle the 'constructor' property.
     if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_CONSTRUCTOR)) {
         RootedObject constructor(cx);
         {
-            JSAutoCompartment ac(cx, target);
+            JSAutoRealm ar(cx, target);
             if (!JS_GetClassObject(cx, key, &constructor))
                 return false;
         }
         if (!JS_WrapObject(cx, &constructor))
             return false;
         desc.object().set(wrapper);
         desc.setAttributes(0);
         desc.setGetter(nullptr);
@@ -721,17 +721,17 @@ JSXrayTraits::delete_(JSContext* cx, Han
     // If we're using Object Xrays, we allow callers to attempt to delete any
     // property from the underlying object that they are able to resolve. Note
     // that this deleting may fail if the property is non-configurable.
     JSProtoKey key = getProtoKey(holder);
     bool isObjectOrArrayInstance = (key == JSProto_Object || key == JSProto_Array) &&
                                    !isPrototype(holder);
     if (isObjectOrArrayInstance) {
         RootedObject target(cx, getTargetObject(wrapper));
-        JSAutoCompartment ac(cx, target);
+        JSAutoRealm ar(cx, target);
         JS_MarkCrossZoneId(cx, id);
         Rooted<PropertyDescriptor> desc(cx);
         if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, &desc))
             return false;
         if (desc.object())
             return JS_DeletePropertyById(cx, target, id, result);
     }
     return result.succeed();
@@ -779,17 +779,17 @@ JSXrayTraits::defineProperty(JSContext* 
             return false;
         }
         if (existingDesc.object() && existingDesc.object() != wrapper) {
             JS_ReportErrorASCII(cx, "Not allowed to shadow non-own Xray-resolved property on [Object] or [Array] XrayWrapper");
             return false;
         }
 
         Rooted<PropertyDescriptor> wrappedDesc(cx, desc);
-        JSAutoCompartment ac(cx, target);
+        JSAutoRealm ar(cx, target);
         JS_MarkCrossZoneId(cx, id);
         if (!JS_WrapPropertyDescriptor(cx, &wrappedDesc) ||
             !JS_DefinePropertyById(cx, target, id, wrappedDesc, result))
         {
             return false;
         }
         *defined = true;
         return true;
@@ -798,17 +798,17 @@ JSXrayTraits::defineProperty(JSContext* 
     // For WebExtensions content scripts, we forward the definition of indexed properties. By
     // validating that the key and value are both numbers, we can avoid doing any wrapping.
     if (isInstance && IsTypedArrayKey(key) &&
         CompartmentPrivate::Get(JS::CurrentGlobalOrNull(cx))->isWebExtensionContentScript &&
         desc.isDataDescriptor() && (desc.value().isNumber() || desc.value().isUndefined()) &&
         IsArrayIndex(GetArrayIndexFromId(cx, id)))
     {
         RootedObject target(cx, getTargetObject(wrapper));
-        JSAutoCompartment ac(cx, target);
+        JSAutoRealm ar(cx, target);
         JS_MarkCrossZoneId(cx, id);
         if (!JS_DefinePropertyById(cx, target, id, desc, result))
             return false;
         *defined = true;
         return true;
     }
 
     return true;
@@ -861,17 +861,17 @@ JSXrayTraits::enumerateNames(JSContext* 
 
     JSProtoKey key = getProtoKey(holder);
     if (!isPrototype(holder)) {
         // For Object and Array instances, we expose some properties from the underlying
         // object, but only after filtering them carefully.
         if (key == JSProto_Object || key == JSProto_Array) {
             MOZ_ASSERT(props.empty());
             {
-                JSAutoCompartment ac(cx, target);
+                JSAutoRealm ar(cx, target);
                 AutoIdVector targetProps(cx);
                 if (!js::GetPropertyKeys(cx, target, flags | JSITER_OWNONLY, &targetProps))
                     return false;
                 // Loop over the properties, and only pass along the ones that
                 // we determine to be safe.
                 if (!props.reserve(targetProps.length()))
                     return false;
                 for (size_t i = 0; i < targetProps.length(); ++i) {
@@ -1163,17 +1163,17 @@ XrayTraits::getExpandoObjectInternal(JSC
         }
 #endif
         return true;
     }
 
     // The expando object lives in the compartment of the target, so all our
     // work needs to happen there.
     RootedObject head(cx, expandoChain);
-    JSAutoCompartment ac(cx, head);
+    JSAutoRealm ar(cx, head);
 
     // Iterate through the chain, looking for a same-origin object.
     while (head) {
         if (expandoObjectMatchesConsumer(cx, head, origin)) {
             expandoObject.set(head);
             return true;
         }
         head = JS_GetReservedSlot(head, JSSLOT_EXPANDO_NEXT).toObjectOrNull();
@@ -1248,31 +1248,31 @@ XrayTraits::attachExpandoObject(JSContex
 
     // AddRef and store the principal.
     NS_ADDREF(origin);
     JS_SetReservedSlot(expandoObject, JSSLOT_EXPANDO_ORIGIN, JS::PrivateValue(origin));
 
     // Note the exclusive wrapper, if there is one.
     RootedObject wrapperHolder(cx);
     if (exclusiveWrapper) {
-        JSAutoCompartment ac(cx, exclusiveWrapper);
+        JSAutoRealm ar(cx, exclusiveWrapper);
         wrapperHolder = JS_NewObjectWithGivenProto(cx, &gWrapperHolderClass, nullptr);
         if (!wrapperHolder)
             return nullptr;
         JS_SetReservedSlot(wrapperHolder, JSSLOT_WRAPPER_HOLDER_CONTENTS, ObjectValue(*exclusiveWrapper));
     }
     if (!JS_WrapObject(cx, &wrapperHolder))
         return nullptr;
     JS_SetReservedSlot(expandoObject, JSSLOT_EXPANDO_EXCLUSIVE_WRAPPER_HOLDER,
                        ObjectOrNullValue(wrapperHolder));
 
     // Store it on the exclusive wrapper, if there is one.
     if (exclusiveWrapper) {
         RootedObject cachedExpandoObject(cx, expandoObject);
-        JSAutoCompartment ac(cx, exclusiveWrapper);
+        JSAutoRealm ar(cx, exclusiveWrapper);
         if (!JS_WrapObject(cx, &cachedExpandoObject))
             return nullptr;
         JSObject* holder = ensureHolder(cx, exclusiveWrapper);
         if (!holder)
             return nullptr;
         SetCachedXrayExpando(holder, cachedExpandoObject);
     }
 
@@ -1290,17 +1290,17 @@ XrayTraits::attachExpandoObject(JSContex
     return expandoObject;
 }
 
 JSObject*
 XrayTraits::ensureExpandoObject(JSContext* cx, HandleObject wrapper,
                                 HandleObject target)
 {
     // Expando objects live in the target compartment.
-    JSAutoCompartment ac(cx, target);
+    JSAutoRealm ar(cx, target);
     RootedObject expandoObject(cx);
     if (!getExpandoObject(cx, target, wrapper, &expandoObject))
         return nullptr;
     if (!expandoObject) {
         JSObject* consumerGlobal = js::GetGlobalForObjectCrossCompartment(wrapper);
         bool isExclusive = GlobalHasExclusiveExpandos(consumerGlobal);
         expandoObject = attachExpandoObject(cx, target, isExclusive ? wrapper : nullptr,
                                             ObjectPrincipal(wrapper));
@@ -1319,17 +1319,17 @@ XrayTraits::cloneExpandoChain(JSContext*
         RootedObject exclusiveWrapper(cx);
         RootedObject wrapperHolder(cx, JS_GetReservedSlot(oldHead,
                                                           JSSLOT_EXPANDO_EXCLUSIVE_WRAPPER_HOLDER)
                                                          .toObjectOrNull());
         if (wrapperHolder) {
             // The global containing this wrapper holder has an xray for |src|
             // with expandos. Create an xray in the global for |dst| which
             // will be associated with a clone of |src|'s expando object.
-            JSAutoCompartment ac(cx, UncheckedUnwrap(wrapperHolder));
+            JSAutoRealm ar(cx, UncheckedUnwrap(wrapperHolder));
             exclusiveWrapper = dst;
             if (!JS_WrapObject(cx, &exclusiveWrapper))
                 return false;
         }
         RootedObject newHead(cx, attachExpandoObject(cx, dst, exclusiveWrapper,
                                                      GetExpandoObjectPrincipal(oldHead)));
         if (!JS_CopyPropertiesFrom(cx, newHead, oldHead))
             return false;
@@ -1577,27 +1577,27 @@ XrayTraits::resolveOwnProperty(JSContext
     RootedObject expando(cx);
     if (!getExpandoObject(cx, target, wrapper, &expando))
         return false;
 
     // Check for expando properties first. Note that the expando object lives
     // in the target compartment.
     bool found = false;
     if (expando) {
-        JSAutoCompartment ac(cx, expando);
+        JSAutoRealm ar(cx, expando);
         JS_MarkCrossZoneId(cx, id);
         if (!JS_GetOwnPropertyDescriptorById(cx, expando, id, desc))
             return false;
         found = !!desc.object();
     }
 
     // Next, check for ES builtins.
     if (!found && JS_IsGlobalObject(target)) {
         JSProtoKey key = JS_IdToProtoKey(cx, id);
-        JSAutoCompartment ac(cx, target);
+        JSAutoRealm ar(cx, target);
         if (key != JSProto_Null) {
             MOZ_ASSERT(key < JSProto_LIMIT);
             RootedObject constructor(cx);
             if (!JS_GetClassObject(cx, key, &constructor))
                 return false;
             MOZ_ASSERT(constructor);
             desc.value().set(ObjectValue(*constructor));
             found = true;
@@ -1660,17 +1660,17 @@ XPCWrappedNativeXrayTraits::resolveOwnPr
 bool
 XPCWrappedNativeXrayTraits::enumerateNames(JSContext* cx, HandleObject wrapper, unsigned flags,
                                            AutoIdVector& props)
 {
     // Force all native properties to be materialized onto the wrapped native.
     AutoIdVector wnProps(cx);
     {
         RootedObject target(cx, getTargetObject(wrapper));
-        JSAutoCompartment ac(cx, target);
+        JSAutoRealm ar(cx, target);
         if (!js::GetPropertyKeys(cx, target, flags, &wnProps))
             return false;
     }
 
     // Go through the properties we found on the underlying object and see if
     // they appear on the XrayWrapper. If it throws (which may happen if the
     // wrapper is a SecurityWrapper), just clear the exception and move on.
     MOZ_ASSERT(!JS_IsExceptionPending(cx));
@@ -2275,17 +2275,17 @@ XrayWrapper<Base, Traits>::definePropert
     if (!Traits::singleton.defineProperty(cx, wrapper, id, desc, existing_desc, result, &defined))
         return false;
     if (defined)
         return true;
 
     // We're placing an expando. The expando objects live in the target
     // compartment, so we need to enter it.
     RootedObject target(cx, Traits::getTargetObject(wrapper));
-    JSAutoCompartment ac(cx, target);
+    JSAutoRealm ar(cx, target);
     JS_MarkCrossZoneId(cx, id);
 
     // Grab the relevant expando object.
     RootedObject expandoObject(cx, Traits::singleton.ensureExpandoObject(cx, wrapper,
                                                                          target));
     if (!expandoObject)
         return false;
 
@@ -2319,17 +2319,17 @@ XrayWrapper<Base, Traits>::delete_(JSCon
 
     // Check the expando object.
     RootedObject target(cx, Traits::getTargetObject(wrapper));
     RootedObject expando(cx);
     if (!Traits::singleton.getExpandoObject(cx, target, wrapper, &expando))
         return false;
 
     if (expando) {
-        JSAutoCompartment ac(cx, expando);
+        JSAutoRealm ar(cx, expando);
         JS_MarkCrossZoneId(cx, id);
         bool hasProp;
         if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
             return false;
         }
         if (hasProp) {
             return JS_DeletePropertyById(cx, expando, id, result);
         }
@@ -2488,18 +2488,18 @@ XrayWrapper<Base, Traits>::getPrototype(
         return false;
 
     // We want to keep the Xray's prototype distinct from that of content, but
     // only if there's been a set. If there's not an expando, or the expando
     // slot is |undefined|, hand back the default proto, appropriately wrapped.
 
     if (expando) {
         RootedValue v(cx);
-        { // Scope for JSAutoCompartment
-            JSAutoCompartment ac(cx, expando);
+        { // Scope for JSAutoRealm
+            JSAutoRealm ar(cx, expando);
             v = JS_GetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE);
         }
         if (!v.isUndefined()) {
             protop.set(v.toObjectOrNull());
             return JS_WrapObject(cx, protop);
         }
     }
 
@@ -2532,18 +2532,18 @@ XrayWrapper<Base, Traits>::setPrototype(
     if (Base::hasSecurityPolicy())
         return Base::setPrototype(cx, wrapper, proto, result);
 
     RootedObject target(cx, Traits::getTargetObject(wrapper));
     RootedObject expando(cx, Traits::singleton.ensureExpandoObject(cx, wrapper, target));
     if (!expando)
         return false;
 
-    // The expando lives in the target's compartment, so do our installation there.
-    JSAutoCompartment ac(cx, target);
+    // The expando lives in the target's realm, so do our installation there.
+    JSAutoRealm ar(cx, target);
 
     RootedValue v(cx, ObjectOrNullValue(proto));
     if (!JS_WrapValue(cx, &v))
         return false;
     JS_SetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE, v);
     return result.succeed();
 }
 
@@ -2586,17 +2586,17 @@ XrayWrapper<Base, Traits>::getPropertyKe
     // Enumerate expando properties first. Note that the expando object lives
     // in the target compartment.
     RootedObject target(cx, Traits::getTargetObject(wrapper));
     RootedObject expando(cx);
     if (!Traits::singleton.getExpandoObject(cx, target, wrapper, &expando))
         return false;
 
     if (expando) {
-        JSAutoCompartment ac(cx, expando);
+        JSAutoRealm ar(cx, expando);
         if (!js::GetPropertyKeys(cx, expando, flags, &props))
             return false;
     }
     for (size_t i = 0; i < props.length(); ++i)
         JS_MarkCrossZoneId(cx, props[i]);
 
     return Traits::singleton.enumerateNames(cx, wrapper, flags, props);
 }
--- a/js/xpconnect/wrappers/XrayWrapper.h
+++ b/js/xpconnect/wrappers/XrayWrapper.h
@@ -300,17 +300,17 @@ public:
             if (protoKey == JSProto_Null) {
                 protop.set(nullptr);
                 return true;
             }
             key = protoKey;
         }
 
         {
-            JSAutoCompartment ac(cx, target);
+            JSAutoRealm ar(cx, target);
             if (!JS_GetClassPrototype(cx, key, protop))
                 return false;
         }
         return JS_WrapObject(cx, protop);
     }
 
     virtual void preserveWrapper(JSObject* target) override {
         // In the case of pure JS objects, there is no underlying object, and
@@ -414,17 +414,17 @@ public:
     bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
                       JS::HandleObject target,
                       JS::MutableHandleObject protop)
     {
         // Opaque wrappers just get targetGlobal.Object.prototype as their
         // prototype. This is preferable to using a null prototype because it
         // lets things like |toString| and |__proto__| work.
         {
-            JSAutoCompartment ac(cx, target);
+            JSAutoRealm ar(cx, target);
             if (!JS_GetClassPrototype(cx, JSProto_Object, protop))
                 return false;
         }
         return JS_WrapObject(cx, protop);
     }
 
     static bool getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance,
                                 js::ESClass* cls) {
--- a/netwerk/base/ProxyAutoConfig.cpp
+++ b/netwerk/base/ProxyAutoConfig.cpp
@@ -646,29 +646,29 @@ private:
     JS_SetNativeStackQuota(mContext, 128 * sizeof(size_t) * 1024);
 
     JS::SetWarningReporter(mContext, PACWarningReporter);
 
     if (!JS::InitSelfHostedCode(mContext)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    JSAutoRequest ar(mContext);
+    JSAutoRequest areq(mContext);
 
     JS::CompartmentOptions options;
     options.creationOptions().setSystemZone();
     mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr,
                                  JS::DontFireOnNewGlobalHook, options);
     if (!mGlobal) {
       JS_ClearPendingException(mContext);
       return NS_ERROR_OUT_OF_MEMORY;
     }
     JS::Rooted<JSObject*> global(mContext, mGlobal);
 
-    JSAutoCompartment ac(mContext, global);
+    JSAutoRealm ar(mContext, global);
     AutoPACErrorReporter aper(mContext);
     if (!JS_InitStandardClasses(mContext, global)) {
       return NS_ERROR_FAILURE;
     }
     if (!JS_DefineFunctions(mContext, global, PACGlobalFunctions)) {
       return NS_ERROR_FAILURE;
     }
 
@@ -732,18 +732,18 @@ ProxyAutoConfig::SetupJS()
 
   NS_GetCurrentThread()->SetCanInvokeJS(true);
 
   mJSContext = JSContextWrapper::Create(mExtraHeapSize);
   if (!mJSContext)
     return NS_ERROR_FAILURE;
 
   JSContext* cx = mJSContext->Context();
-  JSAutoRequest ar(cx);
-  JSAutoCompartment ac(cx, mJSContext->Global());
+  JSAutoRequest areq(cx);
+  JSAutoRealm ar(cx, mJSContext->Global());
   AutoPACErrorReporter aper(cx);
 
   // check if this is a data: uri so that we don't spam the js console with
   // huge meaningless strings. this is not on the main thread, so it can't
   // use nsIURI scheme methods
   bool isDataURI = nsDependentCSubstring(mPACURI, 0, 5).LowerCaseEqualsASCII("data:", 5);
 
   SetRunning(this);
@@ -792,18 +792,18 @@ ProxyAutoConfig::GetProxyForURI(const ns
 {
   if (mJSNeedsSetup)
     SetupJS();
 
   if (!mJSContext || !mJSContext->IsOK())
     return NS_ERROR_NOT_AVAILABLE;
 
   JSContext *cx = mJSContext->Context();
-  JSAutoRequest ar(cx);
-  JSAutoCompartment ac(cx, mJSContext->Global());
+  JSAutoRequest areq(cx);
+  JSAutoRealm ar(cx, mJSContext->Global());
   AutoPACErrorReporter aper(cx);
 
   // the sRunning flag keeps a new PAC file from being installed
   // while the event loop is spinning on a DNS function. Don't early return.
   SetRunning(this);
   mRunningHost = aTestHost;
 
   nsresult rv = NS_ERROR_FAILURE;
@@ -860,17 +860,17 @@ ProxyAutoConfig::GetProxyForURI(const ns
 }
 
 void
 ProxyAutoConfig::GC()
 {
   if (!mJSContext || !mJSContext->IsOK())
     return;
 
-  JSAutoCompartment ac(mJSContext->Context(), mJSContext->Global());
+  JSAutoRealm ar(mJSContext->Context(), mJSContext->Global());
   JS_MaybeGC(mJSContext->Context());
 }
 
 ProxyAutoConfig::~ProxyAutoConfig()
 {
   MOZ_COUNT_DTOR(ProxyAutoConfig);
   MOZ_ASSERT(mShutdown, "Shutdown must be called before dtor.");
   NS_ASSERTION(!mJSContext,
--- a/old-configure.in
+++ b/old-configure.in
@@ -2067,17 +2067,17 @@ dnl to keep that way than testing agains
 case "$MOZ_WIDGET_TOOLKIT" in
 gtk*)
     MOZ_ENABLE_GTK=1
     ;;
 esac
 
 if test "$COMPILE_ENVIRONMENT"; then
   if test "$MOZ_WIDGET_TOOLKIT" = gtk3; then
-    PKG_CHECK_MODULES(MOZ_GTK3, gtk+-3.0 >= $GTK3_VERSION gtk+-unix-print-3.0 glib-2.0 gobject-2.0 $GDK_PACKAGES)
+    PKG_CHECK_MODULES(MOZ_GTK3, gtk+-3.0 >= $GTK3_VERSION gtk+-unix-print-3.0 glib-2.0 gobject-2.0 gio-unix-2.0 $GDK_PACKAGES)
     MOZ_GTK3_CFLAGS="-I${_topsrcdir}/widget/gtk/compat-gtk3 $MOZ_GTK3_CFLAGS"
     TK_CFLAGS=$MOZ_GTK3_CFLAGS
     TK_LIBS=$MOZ_GTK3_LIBS
     dnl GDK_VERSION_MIN_REQUIRED is not set here as GDK3 deprecated warnings
     dnl are suppressed by widget/gtk/compat-gtk3/gdk/gdkversionmacros.h.
     AC_DEFINE_UNQUOTED(GDK_VERSION_MAX_ALLOWED,$GDK_VERSION_MAX_ALLOWED)
     GLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32
   fi
@@ -2086,17 +2086,17 @@ if test "$COMPILE_ENVIRONMENT"; then
   fi
   if test "$MOZ_ENABLE_GTK"; then
     if test "$MOZ_X11"; then
       GDK_PACKAGES=gdk-x11-2.0
     fi
     AC_DEFINE_UNQUOTED(GLIB_VERSION_MIN_REQUIRED,$GLIB_VERSION_MIN_REQUIRED)
     AC_DEFINE_UNQUOTED(GLIB_VERSION_MAX_ALLOWED,$GLIB_VERSION_MAX_ALLOWED)
 
-    PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 glib-2.0 >= $GLIB_VERSION gobject-2.0 $GDK_PACKAGES)
+    PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 glib-2.0 >= $GLIB_VERSION gobject-2.0 gio-unix-2.0 $GDK_PACKAGES)
     MOZ_GTK2_CFLAGS="-I${_topsrcdir}/widget/gtk/compat $MOZ_GTK2_CFLAGS"
   fi
   if test "$MOZ_WIDGET_TOOLKIT" = gtk2; then
     TK_CFLAGS=$MOZ_GTK2_CFLAGS
     TK_LIBS=$MOZ_GTK2_LIBS
   fi
 fi # COMPILE_ENVIRONMENT
 
--- a/testing/web-platform/meta/mediacapture-streams/historical.html.ini
+++ b/testing/web-platform/meta/mediacapture-streams/historical.html.ini
@@ -1,7 +1,3 @@
 [historical.html]
   [navigator.mozGetUserMedia should not exist]
     expected: FAIL
-
-  [Passing MediaStream to URL.createObjectURL() should throw]
-    expected: FAIL
-
--- a/toolkit/components/extensions/MatchPattern.cpp
+++ b/toolkit/components/extensions/MatchPattern.cpp
@@ -723,17 +723,17 @@ MatchGlob::Init(JSContext* aCx, const ns
 bool
 MatchGlob::Matches(const nsAString& aString) const
 {
   if (mRegExp) {
     AutoJSAPI jsapi;
     jsapi.Init();
     JSContext* cx = jsapi.cx();
 
-    JSAutoCompartment ac(cx, mRegExp);
+    JSAutoRealm ar(cx, mRegExp);
 
     JS::RootedObject regexp(cx, mRegExp);
     JS::RootedValue result(cx);
 
     nsString input(aString);
 
     size_t index = 0;
     if (!JS_ExecuteRegExpNoStatics(cx, regexp, input.BeginWriting(), aString.Length(),
--- a/toolkit/components/mozintl/MozIntlHelper.cpp
+++ b/toolkit/components/mozintl/MozIntlHelper.cpp
@@ -25,17 +25,17 @@ AddFunctions(JSContext* cx, JS::Handle<J
     return NS_ERROR_INVALID_ARG;
   }
 
   JS::Rooted<JSObject*> realIntlObj(cx, js::CheckedUnwrap(&val.toObject()));
   if (!realIntlObj) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  JSAutoCompartment ac(cx, realIntlObj);
+  JSAutoRealm ar(cx, realIntlObj);
 
   if (!JS_DefineFunctions(cx, realIntlObj, funcs)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
@@ -68,17 +68,17 @@ MozIntlHelper::AddDateTimeFormatConstruc
     return NS_ERROR_INVALID_ARG;
   }
 
   JS::Rooted<JSObject*> realIntlObj(cx, js::CheckedUnwrap(&val.toObject()));
   if (!realIntlObj) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  JSAutoCompartment ac(cx, realIntlObj);
+  JSAutoRealm ar(cx, realIntlObj);
 
   if (!js::AddMozDateTimeFormatConstructor(cx, realIntlObj)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
@@ -89,17 +89,17 @@ MozIntlHelper::AddRelativeTimeFormatCons
     return NS_ERROR_INVALID_ARG;
   }
 
   JS::Rooted<JSObject*> realIntlObj(cx, js::CheckedUnwrap(&val.toObject()));
   if (!realIntlObj) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  JSAutoCompartment ac(cx, realIntlObj);
+  JSAutoRealm ar(cx, realIntlObj);
 
   if (!js::AddRelativeTimeFormatConstructor(cx, realIntlObj)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
--- a/toolkit/mozapps/installer/windows/nsis/common.nsh
+++ b/toolkit/mozapps/installer/windows/nsis/common.nsh
@@ -8109,8 +8109,54 @@
 
   ; Convert from milliseconds to seconds
   System::Int64Op $0 / 1000
   Pop $0
 
   Pop $1
   Exch $0 ; return elapsed seconds
 !macroend
+
+/**
+ * Create a process to execute a command line. If it is successfully created,
+ * wait on it with WaitForInputIdle, to avoid exiting the current process too
+ * early (exiting early can cause the created process's windows to be opened in
+ * the background).
+ *
+ * CMDLINE Is the command line to execute, like the argument to Exec
+ */
+!define ExecAndWaitForInputIdle "!insertmacro ExecAndWaitForInputIdle_"
+!define CREATE_DEFAULT_ERROR_MODE 0x04000000
+!macro ExecAndWaitForInputIdle_ CMDLINE
+  ; derived from https://stackoverflow.com/a/13960786/3444805 by Anders Kjersem
+  Push $0
+  Push $1
+  Push $2
+
+  ; Command line
+  StrCpy $0 ${CMDLINE}
+
+  ; STARTUPINFO
+  System::Alloc 68
+  Pop $1
+  ; fill in STARTUPINFO.cb (first field) with sizeof(STARTUPINFO)
+  System::Call "*$1(i 68)"
+
+  ; PROCESS_INFORMATION
+  System::Call "*(i, i, i, i) i . r2"
+
+  ; CREATE_DEFAULT_ERROR_MODE follows NSIS myCreateProcess used in Exec
+  System::Call "kernel32::CreateProcessW(i 0, t r0, i 0, i 0, i 0, i ${CREATE_DEFAULT_ERROR_MODE}, i 0, i 0, i r1, i r2) i . r0"
+
+  System::Free $1
+  ${If} $0 <> 0
+    System::Call "*$2(i . r0, i . r1)"
+    ; $0: hProcess, $1: hThread
+    System::Call "user32::WaitForInputIdle(i $0, i 10000)"
+    System::Call "kernel32::CloseHandle(i $0)"
+    System::Call "kernel32::CloseHandle(i $1)"
+  ${EndIf}
+  System::Free $2
+
+  Pop $2
+  Pop $1
+  Pop $0
+!macroend
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -2093,17 +2093,24 @@ LaunchCallbackApp(const NS_tchar *workin
 #if defined(USE_EXECV)
   execv(argv[0], argv);
 #elif defined(XP_MACOSX)
   LaunchChild(argc, (const char**)argv);
 #elif defined(XP_WIN)
   // Do not allow the callback to run when running an update through the
   // service as session 0.  The unelevated updater.exe will do the launching.
   if (!usingService) {
-    WinLaunchChild(argv[0], argc, argv, nullptr);
+    HANDLE hProcess;
+    if (WinLaunchChild(argv[0], argc, argv, nullptr, &hProcess)) {
+      // Keep the current process around until the callback process has created
+      // its message queue, to avoid the launched process's windows being forced
+      // into the background.
+      WaitForInputIdle(hProcess, kWaitForInputIdleTimeoutMS);
+      CloseHandle(hProcess);
+    }
   }
 #else
 # warning "Need implementaton of LaunchCallbackApp"
 #endif
 }
 
 static bool
 WriteStatusFile(const char* aStatus)
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1789,18 +1789,24 @@ static nsresult LaunchChild(nsINativeApp
     return rv;
 
 #if defined(XP_WIN)
   nsAutoString exePath;
   rv = lf->GetPath(exePath);
   if (NS_FAILED(rv))
     return rv;
 
-  if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
+  HANDLE hProcess;
+  if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, nullptr, &hProcess))
     return NS_ERROR_FAILURE;
+  // Keep the current process around until the restarted process has created
+  // its message queue, to avoid the launched process's windows being forced
+  // into the background.
+  ::WaitForInputIdle(hProcess, kWaitForInputIdleTimeoutMS);
+  ::CloseHandle(hProcess);
 
 #else
   nsAutoCString exePath;
   rv = lf->GetNativePath(exePath);
   if (NS_FAILED(rv))
     return rv;
 
 #if defined(XP_UNIX)
--- a/widget/gtk/nsClipboardWayland.cpp
+++ b/widget/gtk/nsClipboardWayland.cpp
@@ -666,19 +666,20 @@ void
 nsRetrievalContextWayland::TransferFastTrackClipboard(
     int aClipboardRequestNumber, GtkSelectionData *aSelectionData)
 {
     if (mClipboardRequestNumber == aClipboardRequestNumber) {
         int dataLength = gtk_selection_data_get_length(aSelectionData);
         if (dataLength > 0) {
             mClipboardDataLength = dataLength;
             mClipboardData = reinterpret_cast<char*>(
-                g_malloc(sizeof(char)*mClipboardDataLength));
+                g_malloc(sizeof(char)*(mClipboardDataLength+1)));
             memcpy(mClipboardData, gtk_selection_data_get_data(aSelectionData),
                    sizeof(char)*mClipboardDataLength);
+            mClipboardData[mClipboardDataLength] = '\0';
         }
     } else {
         NS_WARNING("Received obsoleted clipboard data!");
     }
 }
 
 const char*
 nsRetrievalContextWayland::GetClipboardData(const char* aMimeType,
--- a/xpcom/base/nsWindowsHelpers.h
+++ b/xpcom/base/nsWindowsHelpers.h
@@ -363,9 +363,14 @@ LoadLibrarySystem32(LPCWSTR aModule)
   if (!ConstructSystem32Path(aModule, systemPath, MAX_PATH + 1)) {
     return NULL;
   }
   return LoadLibraryW(systemPath);
 }
 
 }
 
+// How long to wait for a created process to become available for input,
+// to prevent that process's windows being forced to the background.
+// This is used across update, restart, and the launcher.
+const DWORD kWaitForInputIdleTimeoutMS = 10*1000;
+
 #endif