Bug 1618258 - Part 1: Rename FinalizationGroup to FinalizationRegistry. r=jonco
authorAndré Bargull <andre.bargull@gmail.com>
Mon, 16 Mar 2020 10:41:08 +0000
changeset 518933 22db48634a518a8566fe523137834b526feea3d0
parent 518932 f0436db3d379f4e1ef12d74747133ae4f178d3e7
child 518934 9bc13dc77f977f2d33bc1a581d26ea52bf780ff2
push id37220
push useraiakab@mozilla.com
push dateTue, 17 Mar 2020 05:13:41 +0000
treeherdermozilla-central@17adc9cb1db9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1618258
milestone76.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1618258 - Part 1: Rename FinalizationGroup to FinalizationRegistry. r=jonco Differential Revision: https://phabricator.services.mozilla.com/D66930
js/public/GCAPI.h
js/public/ProtoKey.h
js/src/builtin/FinalizationGroupObject.cpp
js/src/builtin/FinalizationGroupObject.h
js/src/builtin/FinalizationRegistryObject.cpp
js/src/builtin/FinalizationRegistryObject.h
js/src/gc/FinalizationGroup.cpp
js/src/gc/FinalizationRegistry.cpp
js/src/gc/GC.cpp
js/src/gc/GCEnum.h
js/src/gc/GCRuntime.h
js/src/gc/GenerateStatsPhases.py
js/src/gc/RootMarking.cpp
js/src/gc/Zone.h
js/src/gc/moz.build
js/src/js.msg
js/src/jsapi.cpp
js/src/jsapi.h
js/src/moz.build
js/src/shell/js.cpp
js/src/shell/jsshell.h
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
modules/libpref/init/StaticPrefList.yaml
xpcom/base/CycleCollectedJSContext.cpp
xpcom/base/CycleCollectedJSContext.h
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -390,24 +390,24 @@ typedef void (*JSFinalizeCallback)(JSFre
 
 typedef void (*JSWeakPointerZonesCallback)(JSContext* cx, void* data);
 
 typedef void (*JSWeakPointerCompartmentCallback)(JSContext* cx,
                                                  JS::Compartment* comp,
                                                  void* data);
 
 /*
- * This is called to tell the embedding that the FinalizationGroup object
- * |group| has cleanup work, and that then engine should be called back at an
+ * This is called to tell the embedding that the FinalizationRegistry object
+ * |registry| has cleanup work, and that then engine should be called back at an
  * appropriate later time to perform this cleanup.
  *
  * This callback must not do anything that could cause GC.
  */
-using JSHostCleanupFinalizationGroupCallback = void (*)(JSObject* group,
-                                                        void* data);
+using JSHostCleanupFinalizationRegistryCallback = void (*)(JSObject* registry,
+                                                           void* data);
 
 /**
  * Each external string has a pointer to JSExternalStringCallbacks. Embedders
  * can use this to implement custom finalization or memory reporting behavior.
  */
 struct JSExternalStringCallbacks {
   /**
    * Finalizes external strings created by JS_NewExternalString. The finalizer
@@ -1100,18 +1100,18 @@ extern JS_PUBLIC_API const JSExternalStr
 JS_GetExternalStringCallbacks(JSString* str);
 
 namespace JS {
 
 extern JS_PUBLIC_API bool IsIdleGCTaskNeeded(JSRuntime* rt);
 
 extern JS_PUBLIC_API void RunIdleTimeGCTask(JSRuntime* rt);
 
-extern JS_PUBLIC_API void SetHostCleanupFinalizationGroupCallback(
-    JSContext* cx, JSHostCleanupFinalizationGroupCallback cb, void* data);
+extern JS_PUBLIC_API void SetHostCleanupFinalizationRegistryCallback(
+    JSContext* cx, JSHostCleanupFinalizationRegistryCallback cb, void* data);
 
 /**
  * Clear kept alive objects in JS WeakRef.
  * https://tc39.es/proposal-weakrefs/#sec-clear-kept-objects
  */
 extern JS_PUBLIC_API void ClearKeptObjects(JSContext* cx);
 
 }  // namespace JS
--- a/js/public/ProtoKey.h
+++ b/js/public/ProtoKey.h
@@ -122,17 +122,17 @@
   REAL(ByteLengthQueuingStrategy, &js::ByteLengthQueuingStrategy::class_)     \
   REAL(CountQueuingStrategy, &js::CountQueuingStrategy::class_)               \
   REAL(WebAssembly, CLASP(WebAssembly))                                       \
   REAL(WasmModule, OCLASP(WasmModule))                                        \
   REAL(WasmInstance, OCLASP(WasmInstance))                                    \
   REAL(WasmMemory, OCLASP(WasmMemory))                                        \
   REAL(WasmTable, OCLASP(WasmTable))                                          \
   REAL(WasmGlobal, OCLASP(WasmGlobal))                                        \
-  REAL(FinalizationGroup, OCLASP(FinalizationGroup))                          \
+  REAL(FinalizationRegistry, OCLASP(FinalizationRegistry))                    \
   REAL(WeakRef, OCLASP(WeakRef))
 
 #define JS_FOR_PROTOTYPES(REAL, IMAGINARY)                      \
   JS_FOR_PROTOTYPES_(REAL, IMAGINARY, IF_INTL(REAL, IMAGINARY), \
                      IF_TYPEDOBJ(REAL, IMAGINARY))
 
 #define JS_FOR_EACH_PROTOTYPE(MACRO) JS_FOR_PROTOTYPES(MACRO, MACRO)
 
rename from js/src/builtin/FinalizationGroupObject.cpp
rename to js/src/builtin/FinalizationRegistryObject.cpp
--- a/js/src/builtin/FinalizationGroupObject.cpp
+++ b/js/src/builtin/FinalizationRegistryObject.cpp
@@ -1,17 +1,17 @@
 /* -*- 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/. */
 
-// Implementation of JS FinalizationGroup objects.
+// Implementation of JS FinalizationRegistry objects.
 
-#include "builtin/FinalizationGroupObject.h"
+#include "builtin/FinalizationRegistryObject.h"
 
 #include "mozilla/ScopeExit.h"
 
 #include "gc/Zone.h"
 #include "vm/GlobalObject.h"
 
 #include "vm/JSObject-inl.h"
 #include "vm/NativeObject-inl.h"
@@ -36,76 +36,78 @@ const JSClassOps FinalizationRecordObjec
     nullptr,                          // call
     nullptr,                          // hasInstance
     nullptr,                          // construct
     FinalizationRecordObject::trace,  // trace
 };
 
 /* static */
 FinalizationRecordObject* FinalizationRecordObject::create(
-    JSContext* cx, HandleFinalizationGroupObject group, HandleValue heldValue) {
-  MOZ_ASSERT(group);
+    JSContext* cx, HandleFinalizationRegistryObject registry,
+    HandleValue heldValue) {
+  MOZ_ASSERT(registry);
 
   auto record = NewObjectWithNullTaggedProto<FinalizationRecordObject>(cx);
   if (!record) {
     return nullptr;
   }
 
-  MOZ_ASSERT(group->compartment() == record->compartment());
+  MOZ_ASSERT(registry->compartment() == record->compartment());
 
-  record->initReservedSlot(WeakGroupSlot, PrivateValue(group));
+  record->initReservedSlot(WeakRegistrySlot, PrivateValue(registry));
   record->initReservedSlot(HeldValueSlot, heldValue);
 
   return record;
 }
 
-FinalizationGroupObject* FinalizationRecordObject::groupDuringGC(
+FinalizationRegistryObject* FinalizationRecordObject::registryDuringGC(
     gc::GCRuntime* gc) const {
-  FinalizationGroupObject* group = groupUnbarriered();
+  FinalizationRegistryObject* registry = registryUnbarriered();
 
   // Perform a manual read barrier. This is the only place where the GC itself
   // needs to perform a read barrier so we must work around our assertions that
   // this doesn't happen.
-  if (group->zone()->isGCMarking()) {
-    FinalizationGroupObject* tmp = group;
+  if (registry->zone()->isGCMarking()) {
+    FinalizationRegistryObject* tmp = registry;
     TraceManuallyBarrieredEdge(&gc->marker, &tmp,
-                               "FinalizationGroup read barrier");
-    MOZ_ASSERT(tmp == group);
-  } else if (group->isMarkedGray()) {
-    gc::UnmarkGrayGCThingUnchecked(gc->rt, JS::GCCellPtr(group));
+                               "FinalizationRegistry read barrier");
+    MOZ_ASSERT(tmp == registry);
+  } else if (registry->isMarkedGray()) {
+    gc::UnmarkGrayGCThingUnchecked(gc->rt, JS::GCCellPtr(registry));
   }
 
-  return group;
+  return registry;
 }
 
-FinalizationGroupObject* FinalizationRecordObject::groupUnbarriered() const {
-  Value value = getReservedSlot(WeakGroupSlot);
+FinalizationRegistryObject* FinalizationRecordObject::registryUnbarriered()
+    const {
+  Value value = getReservedSlot(WeakRegistrySlot);
   if (value.isUndefined()) {
     return nullptr;
   }
-  return static_cast<FinalizationGroupObject*>(value.toPrivate());
+  return static_cast<FinalizationRegistryObject*>(value.toPrivate());
 }
 
 Value FinalizationRecordObject::heldValue() const {
   return getReservedSlot(HeldValueSlot);
 }
 
 bool FinalizationRecordObject::isActive() const {
-  MOZ_ASSERT_IF(!groupUnbarriered(), heldValue().isUndefined());
-  return groupUnbarriered();
+  MOZ_ASSERT_IF(!registryUnbarriered(), heldValue().isUndefined());
+  return registryUnbarriered();
 }
 
 void FinalizationRecordObject::clear() {
-  MOZ_ASSERT(groupUnbarriered());
-  setReservedSlot(WeakGroupSlot, UndefinedValue());
+  MOZ_ASSERT(registryUnbarriered());
+  setReservedSlot(WeakRegistrySlot, UndefinedValue());
   setReservedSlot(HeldValueSlot, UndefinedValue());
 }
 
 bool FinalizationRecordObject::sweep() {
-  FinalizationGroupObject* obj = groupUnbarriered();
+  FinalizationRegistryObject* obj = registryUnbarriered();
   MOZ_ASSERT(obj);
 
   if (IsAboutToBeFinalizedUnbarriered(&obj)) {
     clear();
     return false;
   }
 
   return true;
@@ -113,25 +115,25 @@ bool FinalizationRecordObject::sweep() {
 
 /* static */
 void FinalizationRecordObject::trace(JSTracer* trc, JSObject* obj) {
   if (!trc->traceWeakEdges()) {
     return;
   }
 
   auto record = &obj->as<FinalizationRecordObject>();
-  FinalizationGroupObject* group = record->groupUnbarriered();
-  if (!group) {
+  FinalizationRegistryObject* registry = record->registryUnbarriered();
+  if (!registry) {
     return;
   }
 
-  TraceManuallyBarrieredEdge(trc, &group,
-                             "FinalizationRecordObject weak group");
-  if (group != record->groupUnbarriered()) {
-    record->setReservedSlot(WeakGroupSlot, PrivateValue(group));
+  TraceManuallyBarrieredEdge(trc, &registry,
+                             "FinalizationRecordObject weak registry");
+  if (registry != record->registryUnbarriered()) {
+    record->setReservedSlot(WeakRegistrySlot, PrivateValue(registry));
   }
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // FinalizationRecordVectorObject
 
 const JSClass FinalizationRecordVectorObject::class_ = {
     "FinalizationRecordVector",
@@ -218,81 +220,81 @@ inline bool FinalizationRecordVectorObje
 
 inline void FinalizationRecordVectorObject::remove(
     HandleFinalizationRecordObject record) {
   MOZ_ASSERT(records());
   records()->eraseIfEqual(record);
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// FinalizationGroupObject
+// FinalizationRegistryObject
 
-// Bug 1600300: FinalizationGroupObject is foreground finalized so that HeapPtr
-// destructors never see referents with released arenas. When this is fixed we
-// may be able to make this background finalized again.
-const JSClass FinalizationGroupObject::class_ = {
-    "FinalizationGroup",
-    JSCLASS_HAS_CACHED_PROTO(JSProto_FinalizationGroup) |
+// Bug 1600300: FinalizationRegistryObject is foreground finalized so that
+// HeapPtr destructors never see referents with released arenas. When this is
+// fixed we may be able to make this background finalized again.
+const JSClass FinalizationRegistryObject::class_ = {
+    "FinalizationRegistry",
+    JSCLASS_HAS_CACHED_PROTO(JSProto_FinalizationRegistry) |
         JSCLASS_HAS_RESERVED_SLOTS(SlotCount) | JSCLASS_FOREGROUND_FINALIZE,
     &classOps_, &classSpec_};
 
-const JSClass FinalizationGroupObject::protoClass_ = {
-    "FinalizationGroupPrototype",
-    JSCLASS_HAS_CACHED_PROTO(JSProto_FinalizationGroup), JS_NULL_CLASS_OPS,
+const JSClass FinalizationRegistryObject::protoClass_ = {
+    "FinalizationRegistryPrototype",
+    JSCLASS_HAS_CACHED_PROTO(JSProto_FinalizationRegistry), JS_NULL_CLASS_OPS,
     &classSpec_};
 
-const JSClassOps FinalizationGroupObject::classOps_ = {
-    nullptr,                            // addProperty
-    nullptr,                            // delProperty
-    nullptr,                            // enumerate
-    nullptr,                            // newEnumerate
-    nullptr,                            // resolve
-    nullptr,                            // mayResolve
-    FinalizationGroupObject::finalize,  // finalize
-    nullptr,                            // call
-    nullptr,                            // hasInstance
-    nullptr,                            // construct
-    FinalizationGroupObject::trace,     // trace
+const JSClassOps FinalizationRegistryObject::classOps_ = {
+    nullptr,                               // addProperty
+    nullptr,                               // delProperty
+    nullptr,                               // enumerate
+    nullptr,                               // newEnumerate
+    nullptr,                               // resolve
+    nullptr,                               // mayResolve
+    FinalizationRegistryObject::finalize,  // finalize
+    nullptr,                               // call
+    nullptr,                               // hasInstance
+    nullptr,                               // construct
+    FinalizationRegistryObject::trace,     // trace
 };
 
-const ClassSpec FinalizationGroupObject::classSpec_ = {
+const ClassSpec FinalizationRegistryObject::classSpec_ = {
     GenericCreateConstructor<construct, 1, gc::AllocKind::FUNCTION>,
-    GenericCreatePrototype<FinalizationGroupObject>,
+    GenericCreatePrototype<FinalizationRegistryObject>,
     nullptr,
     nullptr,
     methods_,
     properties_};
 
-const JSFunctionSpec FinalizationGroupObject::methods_[] = {
+const JSFunctionSpec FinalizationRegistryObject::methods_[] = {
     JS_FN(js_register_str, register_, 2, 0),
     JS_FN(js_unregister_str, unregister, 1, 0),
     JS_FN(js_cleanupSome_str, cleanupSome, 0, 0), JS_FS_END};
 
-const JSPropertySpec FinalizationGroupObject::properties_[] = {
-    JS_STRING_SYM_PS(toStringTag, "FinalizationGroup", JSPROP_READONLY),
+const JSPropertySpec FinalizationRegistryObject::properties_[] = {
+    JS_STRING_SYM_PS(toStringTag, "FinalizationRegistry", JSPROP_READONLY),
     JS_PS_END};
 
 /* static */
-bool FinalizationGroupObject::construct(JSContext* cx, unsigned argc,
-                                        Value* vp) {
+bool FinalizationRegistryObject::construct(JSContext* cx, unsigned argc,
+                                           Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
-  if (!ThrowIfNotConstructing(cx, args, "FinalizationGroup")) {
+  if (!ThrowIfNotConstructing(cx, args, "FinalizationRegistry")) {
     return false;
   }
 
   RootedObject cleanupCallback(
       cx, ValueToCallable(cx, args.get(0), 1, NO_CONSTRUCT));
   if (!cleanupCallback) {
     return false;
   }
 
   RootedObject proto(cx);
-  if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_FinalizationGroup,
-                                          &proto)) {
+  if (!GetPrototypeFromBuiltinConstructor(
+          cx, args, JSProto_FinalizationRegistry, &proto)) {
     return false;
   }
 
   Rooted<UniquePtr<ObjectWeakMap>> registrations(
       cx, cx->make_unique<ObjectWeakMap>(cx));
   if (!registrations) {
     return false;
   }
@@ -304,166 +306,169 @@ bool FinalizationGroupObject::construct(
   }
 
   Rooted<UniquePtr<FinalizationRecordVector>> recordsToBeCleanedUp(
       cx, cx->make_unique<FinalizationRecordVector>(cx->zone()));
   if (!recordsToBeCleanedUp) {
     return false;
   }
 
-  FinalizationGroupObject* group =
-      NewObjectWithClassProto<FinalizationGroupObject>(cx, proto);
-  if (!group) {
+  FinalizationRegistryObject* registry =
+      NewObjectWithClassProto<FinalizationRegistryObject>(cx, proto);
+  if (!registry) {
     return false;
   }
 
-  group->initReservedSlot(CleanupCallbackSlot, ObjectValue(*cleanupCallback));
-  InitReservedSlot(group, RegistrationsSlot, registrations.release(),
-                   MemoryUse::FinalizationGroupRegistrations);
-  InitReservedSlot(group, ActiveRecords, activeRecords.release(),
-                   MemoryUse::FinalizationGroupRecordSet);
-  InitReservedSlot(group, RecordsToBeCleanedUpSlot,
+  registry->initReservedSlot(CleanupCallbackSlot,
+                             ObjectValue(*cleanupCallback));
+  InitReservedSlot(registry, RegistrationsSlot, registrations.release(),
+                   MemoryUse::FinalizationRegistryRegistrations);
+  InitReservedSlot(registry, ActiveRecords, activeRecords.release(),
+                   MemoryUse::FinalizationRegistryRecordSet);
+  InitReservedSlot(registry, RecordsToBeCleanedUpSlot,
                    recordsToBeCleanedUp.release(),
-                   MemoryUse::FinalizationGroupRecordVector);
-  group->initReservedSlot(IsQueuedForCleanupSlot, BooleanValue(false));
-  group->initReservedSlot(IsCleanupJobActiveSlot, BooleanValue(false));
+                   MemoryUse::FinalizationRegistryRecordVector);
+  registry->initReservedSlot(IsQueuedForCleanupSlot, BooleanValue(false));
+  registry->initReservedSlot(IsCleanupJobActiveSlot, BooleanValue(false));
 
-  args.rval().setObject(*group);
+  args.rval().setObject(*registry);
   return true;
 }
 
 /* static */
-void FinalizationGroupObject::trace(JSTracer* trc, JSObject* obj) {
-  auto group = &obj->as<FinalizationGroupObject>();
-  if (ObjectWeakMap* registrations = group->registrations()) {
+void FinalizationRegistryObject::trace(JSTracer* trc, JSObject* obj) {
+  auto registry = &obj->as<FinalizationRegistryObject>();
+  if (ObjectWeakMap* registrations = registry->registrations()) {
     registrations->trace(trc);
   }
-  if (FinalizationRecordSet* records = group->activeRecords()) {
+  if (FinalizationRecordSet* records = registry->activeRecords()) {
     records->trace(trc);
   }
-  if (FinalizationRecordVector* records = group->recordsToBeCleanedUp()) {
+  if (FinalizationRecordVector* records = registry->recordsToBeCleanedUp()) {
     records->trace(trc);
   }
 }
 
 /* static */
-void FinalizationGroupObject::finalize(JSFreeOp* fop, JSObject* obj) {
-  auto group = &obj->as<FinalizationGroupObject>();
+void FinalizationRegistryObject::finalize(JSFreeOp* fop, JSObject* obj) {
+  auto registry = &obj->as<FinalizationRegistryObject>();
 
-  // Clear the weak pointer to the group in all remaining records.
+  // Clear the weak pointer to the registry in all remaining records.
 
-  // FinalizationGroups are foreground finalized whereas record objects are
+  // FinalizationRegistries are foreground finalized whereas record objects are
   // background finalized, so record objects and guaranteed to still be
   // accessible at this point.
-  MOZ_ASSERT(group->getClass()->flags & JSCLASS_FOREGROUND_FINALIZE);
+  MOZ_ASSERT(registry->getClass()->flags & JSCLASS_FOREGROUND_FINALIZE);
 
-  FinalizationRecordSet* allRecords = group->activeRecords();
+  FinalizationRecordSet* allRecords = registry->activeRecords();
   for (auto r = allRecords->all(); !r.empty(); r.popFront()) {
     auto record = &r.front()->as<FinalizationRecordObject>();
     MOZ_ASSERT(!(record->getClass()->flags & JSCLASS_FOREGROUND_FINALIZE));
-    MOZ_ASSERT(record->zone() == group->zone());
+    MOZ_ASSERT(record->zone() == registry->zone());
     if (record->isActive()) {
       record->clear();
     }
   }
 
-  fop->delete_(obj, group->registrations(),
-               MemoryUse::FinalizationGroupRegistrations);
-  fop->delete_(obj, group->activeRecords(),
-               MemoryUse::FinalizationGroupRecordSet);
-  fop->delete_(obj, group->recordsToBeCleanedUp(),
-               MemoryUse::FinalizationGroupRecordVector);
+  fop->delete_(obj, registry->registrations(),
+               MemoryUse::FinalizationRegistryRegistrations);
+  fop->delete_(obj, registry->activeRecords(),
+               MemoryUse::FinalizationRegistryRecordSet);
+  fop->delete_(obj, registry->recordsToBeCleanedUp(),
+               MemoryUse::FinalizationRegistryRecordVector);
 }
 
-inline JSObject* FinalizationGroupObject::cleanupCallback() const {
+inline JSObject* FinalizationRegistryObject::cleanupCallback() const {
   Value value = getReservedSlot(CleanupCallbackSlot);
   if (value.isUndefined()) {
     return nullptr;
   }
   return &value.toObject();
 }
 
-ObjectWeakMap* FinalizationGroupObject::registrations() const {
+ObjectWeakMap* FinalizationRegistryObject::registrations() const {
   Value value = getReservedSlot(RegistrationsSlot);
   if (value.isUndefined()) {
     return nullptr;
   }
   return static_cast<ObjectWeakMap*>(value.toPrivate());
 }
 
-FinalizationRecordSet* FinalizationGroupObject::activeRecords() const {
+FinalizationRecordSet* FinalizationRegistryObject::activeRecords() const {
   Value value = getReservedSlot(ActiveRecords);
   if (value.isUndefined()) {
     return nullptr;
   }
   return static_cast<FinalizationRecordSet*>(value.toPrivate());
 }
 
-FinalizationRecordVector* FinalizationGroupObject::recordsToBeCleanedUp()
+FinalizationRecordVector* FinalizationRegistryObject::recordsToBeCleanedUp()
     const {
   Value value = getReservedSlot(RecordsToBeCleanedUpSlot);
   if (value.isUndefined()) {
     return nullptr;
   }
   return static_cast<FinalizationRecordVector*>(value.toPrivate());
 }
 
-bool FinalizationGroupObject::isQueuedForCleanup() const {
+bool FinalizationRegistryObject::isQueuedForCleanup() const {
   return getReservedSlot(IsQueuedForCleanupSlot).toBoolean();
 }
 
-bool FinalizationGroupObject::isCleanupJobActive() const {
+bool FinalizationRegistryObject::isCleanupJobActive() const {
   return getReservedSlot(IsCleanupJobActiveSlot).toBoolean();
 }
 
-void FinalizationGroupObject::queueRecordToBeCleanedUp(
+void FinalizationRegistryObject::queueRecordToBeCleanedUp(
     FinalizationRecordObject* record) {
   AutoEnterOOMUnsafeRegion oomUnsafe;
   if (!recordsToBeCleanedUp()->append(record)) {
-    oomUnsafe.crash("FinalizationGroupObject::queueRecordsToBeCleanedUp");
+    oomUnsafe.crash("FinalizationRegistryObject::queueRecordsToBeCleanedUp");
   }
 }
 
-void FinalizationGroupObject::setQueuedForCleanup(bool value) {
+void FinalizationRegistryObject::setQueuedForCleanup(bool value) {
   MOZ_ASSERT(value != isQueuedForCleanup());
   setReservedSlot(IsQueuedForCleanupSlot, BooleanValue(value));
 }
 
-void FinalizationGroupObject::setCleanupJobActive(bool value) {
+void FinalizationRegistryObject::setCleanupJobActive(bool value) {
   MOZ_ASSERT(value != isCleanupJobActive());
   setReservedSlot(IsCleanupJobActiveSlot, BooleanValue(value));
 }
 
-// FinalizationGroup.prototype.register(target, heldValue [, unregisterToken ])
-// https://tc39.es/proposal-weakrefs/#sec-finalization-group.prototype.register
+// FinalizationRegistry.prototype.register(target, heldValue [, unregisterToken
+// ])
+// https://tc39.es/proposal-weakrefs/#sec-finalization-registry.prototype.register
 /* static */
-bool FinalizationGroupObject::register_(JSContext* cx, unsigned argc,
-                                        Value* vp) {
+bool FinalizationRegistryObject::register_(JSContext* cx, unsigned argc,
+                                           Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
-  // 1. Let finalizationGroup be the this value.
-  // 2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
-  // 3. If finalizationGroup does not have a [[Cells]] internal slot, throw a
+  // 1. Let finalizationRegistry be the this value.
+  // 2. If Type(finalizationRegistry) is not Object, throw a TypeError
+  // exception.
+  // 3. If finalizationRegistry does not have a [[Cells]] internal slot, throw a
   // TypeError exception.
   if (!args.thisv().isObject() ||
-      !args.thisv().toObject().is<FinalizationGroupObject>()) {
+      !args.thisv().toObject().is<FinalizationRegistryObject>()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                              JSMSG_NOT_A_FINALIZATION_GROUP,
-                              "Receiver of FinalizationGroup.register call");
+                              JSMSG_NOT_A_FINALIZATION_REGISTRY,
+                              "Receiver of FinalizationRegistry.register call");
     return false;
   }
 
-  RootedFinalizationGroupObject group(
-      cx, &args.thisv().toObject().as<FinalizationGroupObject>());
+  RootedFinalizationRegistryObject registry(
+      cx, &args.thisv().toObject().as<FinalizationRegistryObject>());
 
   // 4. If Type(target) is not Object, throw a TypeError exception.
   if (!args.get(0).isObject()) {
-    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                              JSMSG_OBJECT_REQUIRED,
-                              "target argument to FinalizationGroup.register");
+    JS_ReportErrorNumberASCII(
+        cx, GetErrorMessage, nullptr, JSMSG_OBJECT_REQUIRED,
+        "target argument to FinalizationRegistry.register");
     return false;
   }
 
   RootedObject target(cx, &args[0].toObject());
 
   // 5. If SameValue(target, heldValue), throw a TypeError exception.
   if (args.get(1).isObject() && &args.get(1).toObject() == target) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
@@ -473,49 +478,50 @@ bool FinalizationGroupObject::register_(
 
   HandleValue heldValue = args.get(1);
 
   // 6. If Type(unregisterToken) is not Object,
   //    a. If unregisterToken is not undefined, throw a TypeError exception.
   if (!args.get(2).isUndefined() && !args.get(2).isObject()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_BAD_UNREGISTER_TOKEN,
-                              "FinalizationGroup.register");
+                              "FinalizationRegistry.register");
     return false;
   }
 
   RootedObject unregisterToken(cx);
   if (!args.get(2).isUndefined()) {
     unregisterToken = &args[2].toObject();
   }
 
   // Create the finalization record representing this target and heldValue.
   Rooted<FinalizationRecordObject*> record(
-      cx, FinalizationRecordObject::create(cx, group, heldValue));
+      cx, FinalizationRecordObject::create(cx, registry, heldValue));
   if (!record) {
     return false;
   }
 
   // Add the record to the list of records with live targets.
-  if (!group->activeRecords()->put(record)) {
+  if (!registry->activeRecords()->put(record)) {
     ReportOutOfMemory(cx);
     return false;
   }
 
-  auto recordsGuard =
-      mozilla::MakeScopeExit([&] { group->activeRecords()->remove(record); });
+  auto recordsGuard = mozilla::MakeScopeExit(
+      [&] { registry->activeRecords()->remove(record); });
 
   // Add the record to the registrations if an unregister token was supplied.
-  if (unregisterToken && !addRegistration(cx, group, unregisterToken, record)) {
+  if (unregisterToken &&
+      !addRegistration(cx, registry, unregisterToken, record)) {
     return false;
   }
 
   auto registrationsGuard = mozilla::MakeScopeExit([&] {
     if (unregisterToken) {
-      removeRegistrationOnError(group, unregisterToken, record);
+      removeRegistrationOnError(registry, unregisterToken, record);
     }
   });
 
   // Fully unwrap the target to pass it to the GC.
   RootedObject unwrappedTarget(cx);
   unwrappedTarget = CheckedUnwrapDynamic(target, cx);
   if (!unwrappedTarget) {
     ReportAccessDenied(cx);
@@ -526,37 +532,38 @@ bool FinalizationGroupObject::register_(
   RootedObject wrappedRecord(cx, record);
   AutoRealm ar(cx, unwrappedTarget);
   if (!JS_WrapObject(cx, &wrappedRecord)) {
     return false;
   }
 
   // Register the record with the target.
   gc::GCRuntime* gc = &cx->runtime()->gc;
-  if (!gc->registerWithFinalizationGroup(cx, unwrappedTarget, wrappedRecord)) {
+  if (!gc->registerWithFinalizationRegistry(cx, unwrappedTarget,
+                                            wrappedRecord)) {
     return false;
   }
 
   recordsGuard.release();
   registrationsGuard.release();
   args.rval().setUndefined();
   return true;
 }
 
 /* static */
-bool FinalizationGroupObject::addRegistration(
-    JSContext* cx, HandleFinalizationGroupObject group,
+bool FinalizationRegistryObject::addRegistration(
+    JSContext* cx, HandleFinalizationRegistryObject registry,
     HandleObject unregisterToken, HandleFinalizationRecordObject record) {
   // Add the record to the list of records associated with this unregister
   // token.
 
   MOZ_ASSERT(unregisterToken);
-  MOZ_ASSERT(group->registrations());
+  MOZ_ASSERT(registry->registrations());
 
-  auto& map = *group->registrations();
+  auto& map = *registry->registrations();
   Rooted<FinalizationRecordVectorObject*> recordsObject(cx);
   JSObject* obj = map.lookup(unregisterToken);
   if (obj) {
     recordsObject = &obj->as<FinalizationRecordVectorObject>();
   } else {
     recordsObject = FinalizationRecordVectorObject::create(cx);
     if (!recordsObject || !map.add(cx, unregisterToken, recordsObject)) {
       return false;
@@ -566,205 +573,208 @@ bool FinalizationGroupObject::addRegistr
   if (!recordsObject->append(record)) {
     ReportOutOfMemory(cx);
     return false;
   }
 
   return true;
 }
 
-/* static */ void FinalizationGroupObject::removeRegistrationOnError(
-    HandleFinalizationGroupObject group, HandleObject unregisterToken,
+/* static */ void FinalizationRegistryObject::removeRegistrationOnError(
+    HandleFinalizationRegistryObject registry, HandleObject unregisterToken,
     HandleFinalizationRecordObject record) {
   // Remove a registration if something went wrong before we added it to the
   // target zone's map. Note that this can't remove a registration after that
   // point.
 
   MOZ_ASSERT(unregisterToken);
-  MOZ_ASSERT(group->registrations());
+  MOZ_ASSERT(registry->registrations());
   JS::AutoAssertNoGC nogc;
 
-  auto& map = *group->registrations();
+  auto& map = *registry->registrations();
   JSObject* obj = map.lookup(unregisterToken);
   MOZ_ASSERT(obj);
   auto records = &obj->as<FinalizationRecordVectorObject>();
   records->remove(record);
 
   if (records->empty()) {
     map.remove(unregisterToken);
   }
 }
 
-// FinalizationGroup.prototype.unregister ( unregisterToken )
-// https://tc39.es/proposal-weakrefs/#sec-finalization-group.prototype.unregister
+// FinalizationRegistry.prototype.unregister ( unregisterToken )
+// https://tc39.es/proposal-weakrefs/#sec-finalization-registry.prototype.unregister
 /* static */
-bool FinalizationGroupObject::unregister(JSContext* cx, unsigned argc,
-                                         Value* vp) {
+bool FinalizationRegistryObject::unregister(JSContext* cx, unsigned argc,
+                                            Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
-  // 1. Let finalizationGroup be the this value.
-  // 2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
-  // 3. If finalizationGroup does not have a [[Cells]] internal slot, throw a
+  // 1. Let finalizationRegistry be the this value.
+  // 2. If Type(finalizationRegistry) is not Object, throw a TypeError
+  //    exception.
+  // 3. If finalizationRegistry does not have a [[Cells]] internal slot, throw a
   //    TypeError exception.
   if (!args.thisv().isObject() ||
-      !args.thisv().toObject().is<FinalizationGroupObject>()) {
-    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                              JSMSG_NOT_A_FINALIZATION_GROUP,
-                              "Receiver of FinalizationGroup.unregister call");
+      !args.thisv().toObject().is<FinalizationRegistryObject>()) {
+    JS_ReportErrorNumberASCII(
+        cx, GetErrorMessage, nullptr, JSMSG_NOT_A_FINALIZATION_REGISTRY,
+        "Receiver of FinalizationRegistry.unregister call");
     return false;
   }
 
-  RootedFinalizationGroupObject group(
-      cx, &args.thisv().toObject().as<FinalizationGroupObject>());
+  RootedFinalizationRegistryObject registry(
+      cx, &args.thisv().toObject().as<FinalizationRegistryObject>());
 
   // 4. If Type(unregisterToken) is not Object, throw a TypeError exception.
   if (!args.get(0).isObject()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_BAD_UNREGISTER_TOKEN,
-                              "FinalizationGroup.unregister");
+                              "FinalizationRegistry.unregister");
     return false;
   }
 
   RootedObject unregisterToken(cx, &args[0].toObject());
 
   // 5. Let removed be false.
   bool removed = false;
 
   // 6. For each Record { [[Target]], [[HeldValue]], [[UnregisterToken]] } cell
-  //    that is an element of finalizationGroup.[[Cells]], do
+  //    that is an element of finalizationRegistry.[[Cells]], do
   //    a. If SameValue(cell.[[UnregisterToken]], unregisterToken) is true, then
-  //       i. Remove cell from finalizationGroup.[[Cells]].
+  //       i. Remove cell from finalizationRegistry.[[Cells]].
   //       ii. Set removed to true.
 
-  FinalizationRecordSet* activeRecords = group->activeRecords();
-  RootedObject obj(cx, group->registrations()->lookup(unregisterToken));
+  FinalizationRecordSet* activeRecords = registry->activeRecords();
+  RootedObject obj(cx, registry->registrations()->lookup(unregisterToken));
   if (obj) {
     auto* records = obj->as<FinalizationRecordVectorObject>().records();
     MOZ_ASSERT(records);
     MOZ_ASSERT(!records->empty());
     for (FinalizationRecordObject* record : *records) {
       if (record->isActive()) {
         // Clear the fields of this record; it will be removed from the target's
         // list when it is next swept.
         activeRecords->remove(record);
         record->clear();
         removed = true;
       }
 
       MOZ_ASSERT(!activeRecords->has(record));
     }
-    group->registrations()->remove(unregisterToken);
+    registry->registrations()->remove(unregisterToken);
   }
 
   // 7. Return removed.
   args.rval().setBoolean(removed);
   return true;
 }
 
-// FinalizationGroup.prototype.cleanupSome ( [ callback ] )
-// https://tc39.es/proposal-weakrefs/#sec-finalization-group.prototype.cleanupSome
-bool FinalizationGroupObject::cleanupSome(JSContext* cx, unsigned argc,
-                                          Value* vp) {
+// FinalizationRegistry.prototype.cleanupSome ( [ callback ] )
+// https://tc39.es/proposal-weakrefs/#sec-finalization-registry.prototype.cleanupSome
+bool FinalizationRegistryObject::cleanupSome(JSContext* cx, unsigned argc,
+                                             Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
-  // 1. Let finalizationGroup be the this value.
-  // 2. If Type(finalizationGroup) is not Object, throw a TypeError exception.
-  // 3. If finalizationGroup does not have [[Cells]] and
-  //    [[IsFinalizationGroupCleanupJobActive]] internal slots, throw a
+  // 1. Let finalizationRegistry be the this value.
+  // 2. If Type(finalizationRegistry) is not Object, throw a TypeError
+  //    exception.
+  // 3. If finalizationRegistry does not have [[Cells]] and
+  //    [[IsFinalizationRegistryCleanupJobActive]] internal slots, throw a
   //    TypeError exception.
   if (!args.thisv().isObject() ||
-      !args.thisv().toObject().is<FinalizationGroupObject>()) {
-    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                              JSMSG_NOT_A_FINALIZATION_GROUP,
-                              "Receiver of FinalizationGroup.cleanupSome call");
+      !args.thisv().toObject().is<FinalizationRegistryObject>()) {
+    JS_ReportErrorNumberASCII(
+        cx, GetErrorMessage, nullptr, JSMSG_NOT_A_FINALIZATION_REGISTRY,
+        "Receiver of FinalizationRegistry.cleanupSome call");
     return false;
   }
 
-  // 4. If finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] is true,
-  //    throw a TypeError exception.
-  RootedFinalizationGroupObject group(
-      cx, &args.thisv().toObject().as<FinalizationGroupObject>());
-  if (group->isCleanupJobActive()) {
+  // 4. If finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] is
+  //    true, throw a TypeError exception.
+  RootedFinalizationRegistryObject registry(
+      cx, &args.thisv().toObject().as<FinalizationRegistryObject>());
+  if (registry->isCleanupJobActive()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_BAD_CLEANUP_STATE);
     return false;
   }
 
   // 5. If callback is not undefined and IsCallable(callback) is false, throw a
   //    TypeError exception.
   RootedObject cleanupCallback(cx);
   if (!args.get(0).isUndefined()) {
     cleanupCallback = ValueToCallable(cx, args.get(0), -1, NO_CONSTRUCT);
     if (!cleanupCallback) {
       return false;
     }
   }
 
-  if (!cleanupQueuedRecords(cx, group, cleanupCallback)) {
+  if (!cleanupQueuedRecords(cx, registry, cleanupCallback)) {
     return false;
   }
 
   args.rval().setUndefined();
   return true;
 }
 
 /* static */
-bool FinalizationGroupObject::hasRegisteredRecordsToBeCleanedUp(
-    HandleFinalizationGroupObject group) {
-  FinalizationRecordVector* records = group->recordsToBeCleanedUp();
+bool FinalizationRegistryObject::hasRegisteredRecordsToBeCleanedUp(
+    HandleFinalizationRegistryObject registry) {
+  FinalizationRecordVector* records = registry->recordsToBeCleanedUp();
   size_t initialLength = records->length();
   if (initialLength == 0) {
     return false;
   }
 
   for (FinalizationRecordObject* record : *records) {
     if (record->isActive()) {
       return true;
     }
   }
 
   return false;
 }
 
-// CleanupFinalizationGroup ( finalizationGroup [ , callback ] )
-// https://tc39.es/proposal-weakrefs/#sec-cleanup-finalization-group
+// CleanupFinalizationRegistry ( finalizationRegistry [ , callback ] )
+// https://tc39.es/proposal-weakrefs/#sec-cleanup-finalization-registry
 /* static */
-bool FinalizationGroupObject::cleanupQueuedRecords(
-    JSContext* cx, HandleFinalizationGroupObject group,
+bool FinalizationRegistryObject::cleanupQueuedRecords(
+    JSContext* cx, HandleFinalizationRegistryObject registry,
     HandleObject callbackArg) {
-  MOZ_ASSERT(cx->compartment() == group->compartment());
+  MOZ_ASSERT(cx->compartment() == registry->compartment());
 
-  // 2. If CheckForEmptyCells(finalizationGroup) is false, return.
-  if (!hasRegisteredRecordsToBeCleanedUp(group)) {
+  // 2. If CheckForEmptyCells(finalizationRegistry) is false, return.
+  if (!hasRegisteredRecordsToBeCleanedUp(registry)) {
     return true;
   }
 
   // 3. Let iterator be
-  //    !CreateFinalizationGroupCleanupIterator(finalizationGroup).
+  //    !CreateFinalizationRegistryCleanupIterator(finalizationRegistry).
   Rooted<FinalizationIteratorObject*> iterator(
-      cx, FinalizationIteratorObject::create(cx, group));
+      cx, FinalizationIteratorObject::create(cx, registry));
   if (!iterator) {
     return false;
   }
 
   // 4. If callback is undefined, set callback to
-  //    finalizationGroup.[[CleanupCallback]].
+  //    finalizationRegistry.[[CleanupCallback]].
   RootedValue callback(cx);
   if (callbackArg) {
     callback.setObject(*callbackArg);
   } else {
-    JSObject* cleanupCallback = group->cleanupCallback();
+    JSObject* cleanupCallback = registry->cleanupCallback();
     MOZ_ASSERT(cleanupCallback);
     callback.setObject(*cleanupCallback);
   }
 
-  // 5. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to true.
-  group->setCleanupJobActive(true);
+  // 5. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to
+  //    true.
+  registry->setCleanupJobActive(true);
 
-  FinalizationRecordVector* records = group->recordsToBeCleanedUp();
+  FinalizationRecordVector* records = registry->recordsToBeCleanedUp();
 #ifdef DEBUG
   size_t initialLength = records->length();
 #endif
 
   // 6. Let result be Call(callback, undefined, iterator).
   RootedValue iteratorVal(cx, ObjectValue(*iterator));
   RootedValue rval(cx);
   bool ok = Call(cx, callback, UndefinedHandleValue, iteratorVal, &rval);
@@ -772,37 +782,39 @@ bool FinalizationGroupObject::cleanupQue
   // Remove records that were iterated over.
   size_t index = iterator->index();
   MOZ_ASSERT(index <= records->length());
   MOZ_ASSERT(initialLength <= records->length());
   if (index > 0) {
     records->erase(records->begin(), records->begin() + index);
   }
 
-  // 7. Set finalizationGroup.[[IsFinalizationGroupCleanupJobActive]] to false.
-  group->setCleanupJobActive(false);
+  // 7. Set finalizationRegistry.[[IsFinalizationRegistryCleanupJobActive]] to
+  //    false.
+  registry->setCleanupJobActive(false);
 
-  // 8. Set iterator.[[FinalizationGroup]] to empty.
-  iterator->clearFinalizationGroup();
+  // 8. Set iterator.[[FinalizationRegistry]] to empty.
+  iterator->clearFinalizationRegistry();
 
   return ok;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // FinalizationIteratorObject
 
 const JSClass FinalizationIteratorObject::class_ = {
-    "FinalizationGroupCleanupIterator", JSCLASS_HAS_RESERVED_SLOTS(SlotCount),
-    JS_NULL_CLASS_OPS, JS_NULL_CLASS_SPEC};
+    "FinalizationRegistryCleanupIterator",
+    JSCLASS_HAS_RESERVED_SLOTS(SlotCount), JS_NULL_CLASS_OPS,
+    JS_NULL_CLASS_SPEC};
 
 const JSFunctionSpec FinalizationIteratorObject::methods_[] = {
     JS_FN(js_next_str, next, 0, 0), JS_FS_END};
 
 const JSPropertySpec FinalizationIteratorObject::properties_[] = {
-    JS_STRING_SYM_PS(toStringTag, "FinalizationGroup Cleanup Iterator",
+    JS_STRING_SYM_PS(toStringTag, "FinalizationRegistry Cleanup Iterator",
                      JSPROP_READONLY),
     JS_PS_END};
 
 /* static */
 bool GlobalObject::initFinalizationIteratorProto(JSContext* cx,
                                                  Handle<GlobalObject*> global) {
   Rooted<JSObject*> base(
       cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
@@ -818,97 +830,100 @@ bool GlobalObject::initFinalizationItera
                            FinalizationIteratorObject::properties_)) {
     return false;
   }
   global->setReservedSlot(FINALIZATION_ITERATOR_PROTO, ObjectValue(*proto));
   return true;
 }
 
 /* static */ FinalizationIteratorObject* FinalizationIteratorObject::create(
-    JSContext* cx, HandleFinalizationGroupObject group) {
-  MOZ_ASSERT(group);
+    JSContext* cx, HandleFinalizationRegistryObject registry) {
+  MOZ_ASSERT(registry);
 
   RootedObject proto(cx, GlobalObject::getOrCreateFinalizationIteratorPrototype(
                              cx, cx->global()));
   if (!proto) {
     return nullptr;
   }
 
   FinalizationIteratorObject* iterator =
       NewObjectWithGivenProto<FinalizationIteratorObject>(cx, proto);
   if (!iterator) {
     return nullptr;
   }
 
-  iterator->initReservedSlot(FinalizationGroupSlot, ObjectValue(*group));
+  iterator->initReservedSlot(FinalizationRegistrySlot, ObjectValue(*registry));
   iterator->initReservedSlot(IndexSlot, Int32Value(0));
 
   return iterator;
 }
 
-FinalizationGroupObject* FinalizationIteratorObject::finalizationGroup() const {
-  Value value = getReservedSlot(FinalizationGroupSlot);
+FinalizationRegistryObject* FinalizationIteratorObject::finalizationRegistry()
+    const {
+  Value value = getReservedSlot(FinalizationRegistrySlot);
   if (value.isUndefined()) {
     return nullptr;
   }
-  return &value.toObject().as<FinalizationGroupObject>();
+  return &value.toObject().as<FinalizationRegistryObject>();
 }
 
 size_t FinalizationIteratorObject::index() const {
   int32_t i = getReservedSlot(IndexSlot).toInt32();
   MOZ_ASSERT(i >= 0);
   return size_t(i);
 }
 
 void FinalizationIteratorObject::setIndex(size_t i) {
   MOZ_ASSERT(i <= INT32_MAX);
   setReservedSlot(IndexSlot, Int32Value(int32_t(i)));
 }
 
-void FinalizationIteratorObject::clearFinalizationGroup() {
-  MOZ_ASSERT(finalizationGroup());
-  setReservedSlot(FinalizationGroupSlot, UndefinedValue());
+void FinalizationIteratorObject::clearFinalizationRegistry() {
+  MOZ_ASSERT(finalizationRegistry());
+  setReservedSlot(FinalizationRegistrySlot, UndefinedValue());
 }
 
-// %FinalizationGroupCleanupIteratorPrototype%.next()
-// https://tc39.es/proposal-weakrefs/#sec-%finalizationgroupcleanupiterator%.next
+// %FinalizationRegistryCleanupIteratorPrototype%.next()
+// https://tc39.es/proposal-weakrefs/#sec-%finalizationregistrycleanupiterator%.next
 /* static */
 bool FinalizationIteratorObject::next(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
   // 1. Let iterator be the this value.
   // 2. If Type(iterator) is not Object, throw a TypeError exception.
-  // 3. If iterator does not have a [[FinalizationGroup]] internal slot, throw a
-  //    TypeError exception.
+  // 3. If iterator does not have a [[FinalizationRegistry]] internal slot,
+  //    throw a TypeError exception.
   if (!args.thisv().isObject() ||
       !args.thisv().toObject().is<FinalizationIteratorObject>()) {
     JS_ReportErrorNumberASCII(
         cx, GetErrorMessage, nullptr, JSMSG_NOT_A_FINALIZATION_ITERATOR,
-        "Receiver of FinalizationGroupCleanupIterator.next call");
+        "Receiver of FinalizationRegistryCleanupIterator.next call");
     return false;
   }
 
   RootedFinalizationIteratorObject iterator(
       cx, &args.thisv().toObject().as<FinalizationIteratorObject>());
 
-  // 4. If iterator.[[FinalizationGroup]] is empty, throw a TypeError exception.
-  // 5. Let finalizationGroup be iterator.[[FinalizationGroup]].
-  RootedFinalizationGroupObject group(cx, iterator->finalizationGroup());
-  if (!group) {
+  // 4. If iterator.[[FinalizationRegistry]] is empty, throw a TypeError
+  //    exception.
+  // 5. Let finalizationRegistry be iterator.[[FinalizationRegistry]].
+  RootedFinalizationRegistryObject registry(cx,
+                                            iterator->finalizationRegistry());
+  if (!registry) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                              JSMSG_STALE_FINALIZATION_GROUP_ITERATOR);
+                              JSMSG_STALE_FINALIZATION_REGISTRY_ITERATOR);
     return false;
   }
 
-  // 8. If finalizationGroup.[[Cells]] contains a Record cell such that
+  // 8. If finalizationRegistry.[[Cells]] contains a Record cell such that
   //    cell.[[Target]] is empty,
   //    a. Choose any such cell.
-  //    b. Remove cell from finalizationGroup.[[Cells]].
+  //    b. Remove cell from finalizationRegistry.[[Cells]].
   //    c. Return CreateIterResultObject(cell.[[HeldValue]], false).
-  FinalizationRecordVector* records = group->recordsToBeCleanedUp();
+  FinalizationRecordVector* records = registry->recordsToBeCleanedUp();
   size_t index = iterator->index();
   MOZ_ASSERT(index <= records->length());
 
   // Advance until we find a record that hasn't been unregistered.
   while (index < records->length() && index < INT32_MAX &&
          !(*records)[index]->isActive()) {
     index++;
     iterator->setIndex(index);
@@ -917,17 +932,17 @@ bool FinalizationIteratorObject::next(JS
   if (index < records->length() && index < INT32_MAX) {
     RootedFinalizationRecordObject record(cx, (*records)[index]);
     RootedValue heldValue(cx, record->heldValue());
     JSObject* result = CreateIterResultObject(cx, heldValue, false);
     if (!result) {
       return false;
     }
 
-    group->activeRecords()->remove(record);
+    registry->activeRecords()->remove(record);
     record->clear();
     iterator->setIndex(index + 1);
 
     args.rval().setObject(*result);
     return true;
   }
 
   // 9. Otherwise, return CreateIterResultObject(undefined, true).
rename from js/src/builtin/FinalizationGroupObject.h
rename to js/src/builtin/FinalizationRegistryObject.h
--- a/js/src/builtin/FinalizationGroupObject.h
+++ b/js/src/builtin/FinalizationRegistryObject.h
@@ -1,31 +1,31 @@
 /* -*- 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/. */
 
 /*
- * FinalizationGroup objects allow a program to register to receive a callback
- * after a 'target' object dies. The callback is passed a 'held value' (that
- * hopefully doesn't entrain the target). An 'unregister token' is an object
- * which can be used to remove multiple previous registrations in one go.
+ * FinalizationRegistry objects allow a program to register to receive a
+ * callback after a 'target' object dies. The callback is passed a 'held value'
+ * (that hopefully doesn't entrain the target). An 'unregister token' is an
+ * object which can be used to remove multiple previous registrations in one go.
  *
  * To arrange this, the following data structures are used:
  *
  *   +-------------------------------------+---------------------------------+
- *   |    FinalizationGroup compartment    |    Target zone / compartment    |
+ *   |   FinalizationRegistry compartment  |    Target zone / compartment    |
  *   |                                     |                                 |
- *   |         +-------------------+       |      +------------------+       |
- *   |  +----->+ FinalizationGroup |       |      |       Zone       |       |
- *   |  |      +---------+---------+       |      +---------+--------+       |
- *   |  |                |                 |                |                |
- *   |  |                v                 |                v                |
- *   |  |  +-------------+-------------+   |   +------------+------------+   |
+ *   |        +----------------------+     |      +------------------+       |
+ *   |  +---->+ FinalizationRegistry |     |      |       Zone       |       |
+ *   |  |     +---------+------------+     |      +---------+--------+       |
+ *   |  |               |                  |                |                |
+ *   |  |               v                  |                v                |
+ *   |  |  +------------+--------------+   |   +------------+------------+   |
  *   |  |  |       Registrations       |   |   |  FinalizationRecordMap  |   |
  *   |  |  |         weak map          |   |   |           map           |   |
  *   |  |  +---------------------------+   |   +-------------------------+   |
  *   |  |  | Unregister  :   Records   |   |   |  Target  : Finalization-|   |
  *   |  |  |   token     :   object    |   |   |  object  : RecordVector |   |
  *   |  |  +--------------------+------+   |   +----+-------------+------+   |
  *   |  |                       |          |        |             |          |
  *   |  |                       v          |        v             |          |
@@ -35,105 +35,105 @@
  *   |  |  +-------------+-------------+   |   +----------+       |          |
  *   |  |  |       RecordVector        |   |                      |          |
  *   |  |  +-------------+-------------+   |                      |          |
  *   |  |                |                 |                      |          |
  *   |  |              * v                 |                      |          |
  *   |  |  +-------------+-------------+ * |                      |          |
  *   |  |  | FinalizationRecordObject  +<-------------------------+          |
  *   |  |  +---------------------------+   |                                 |
- *   |  +--+ Group                     |   |                                 |
+ *   |  +--+ Registry                  |   |                                 |
  *   |     +---------------------------+   |                                 |
  *   |     | Held value                |   |                                 |
  *   |     +---------------------------+   |                                 |
  *   |                                     |                                 |
  *   +-------------------------------------+---------------------------------+
  *
- * Registering a target with a FinalizationGroup creates a FinalizationRecord
- * containing the group and the heldValue. This is added to a vector of records
- * associated with the target, implemented as a map on the target's Zone. All
- * finalization records are treated as GC roots.
+ * Registering a target with a FinalizationRegistry creates a FinalizationRecord
+ * containing the registry and the heldValue. This is added to a vector of
+ * records associated with the target, implemented as a map on the target's
+ * Zone. All finalization records are treated as GC roots.
  *
  * When a target is registered an unregister token may be supplied. If so, this
- * is also recorded by the group and is stored in a weak map of
+ * is also recorded by the registry and is stored in a weak map of
  * registrations. The values of this map are FinalizationRecordVectorObject
  * objects. It's necessary to have another JSObject here because our weak map
  * implementation only supports JS types as values.
  *
- * After a target object has been registered with a finalization group it is
+ * After a target object has been registered with a finalization registry it is
  * expected that its callback will be called for that object even if the
- * finalization group itself is no longer reachable from JS. Thus the values of
- * each zone's finalization record map are treated as roots and marked at the
+ * finalization registry itself is no longer reachable from JS. Thus the values
+ * of each zone's finalization record map are treated as roots and marked at the
  * start of GC.
  *
  * The finalization record maps are also swept during GC to check for any
  * targets that are dying. For such targets the associated record list is
  * processed and for each record the heldValue is queued on finalization
- * group. At a later time this causes the client's callback to be run.
+ * registry. At a later time this causes the client's callback to be run.
  *
  * When targets are unregistered, the registration is looked up in the weakmap
  * and the corresponding records are cleared. These are removed from the zone's
  * record map when it is next swept.
  */
 
-#ifndef builtin_FinalizationGroupObject_h
-#define builtin_FinalizationGroupObject_h
+#ifndef builtin_FinalizationRegistryObject_h
+#define builtin_FinalizationRegistryObject_h
 
 #include "gc/Barrier.h"
 #include "js/GCVector.h"
 #include "vm/NativeObject.h"
 
 namespace js {
 
-class FinalizationGroupObject;
+class FinalizationRegistryObject;
 class FinalizationIteratorObject;
 class FinalizationRecordObject;
 class ObjectWeakMap;
 
-using HandleFinalizationGroupObject = Handle<FinalizationGroupObject*>;
+using HandleFinalizationRegistryObject = Handle<FinalizationRegistryObject*>;
 using HandleFinalizationRecordObject = Handle<FinalizationRecordObject*>;
-using RootedFinalizationGroupObject = Rooted<FinalizationGroupObject*>;
+using RootedFinalizationRegistryObject = Rooted<FinalizationRegistryObject*>;
 using RootedFinalizationIteratorObject = Rooted<FinalizationIteratorObject*>;
 using RootedFinalizationRecordObject = Rooted<FinalizationRecordObject*>;
 
-// A finalization record: a pair of finalization group and held value.
+// A finalization record: a pair of finalization registry and held value.
 //
 // A finalization record represents the registered interest of a finalization
-// group in a target's finalization.
+// registry in a target's finalization.
 //
 // Finalization records are initially 'active' but may be cleared and become
 // inactive. This happens when:
-//  - the heldValue is passed to the group's cleanup callback
-//  - the group's unregister method removes the registration
-//  - the FinalizationGroup dies
+//  - the heldValue is passed to the registry's cleanup callback
+//  - the registry's unregister method removes the registration
+//  - the FinalizationRegistry dies
 class FinalizationRecordObject : public NativeObject {
-  enum { WeakGroupSlot = 0, HeldValueSlot, SlotCount };
+  enum { WeakRegistrySlot = 0, HeldValueSlot, SlotCount };
 
  public:
   static const JSClass class_;
 
-  // The group can be a CCW to a FinalizationGroupObject.
-  static FinalizationRecordObject* create(JSContext* cx,
-                                          HandleFinalizationGroupObject group,
-                                          HandleValue heldValue);
+  // The registry can be a CCW to a FinalizationRegistryObject.
+  static FinalizationRecordObject* create(
+      JSContext* cx, HandleFinalizationRegistryObject registry,
+      HandleValue heldValue);
 
-  // Read weak group pointer and perform read barrier during GC.
-  FinalizationGroupObject* groupDuringGC(gc::GCRuntime* gc) const;
+  // Read weak registry pointer and perform read barrier during GC.
+  FinalizationRegistryObject* registryDuringGC(gc::GCRuntime* gc) const;
 
   Value heldValue() const;
   bool isActive() const;
   void clear();
   bool sweep();
 
  private:
   static const JSClassOps classOps_;
 
   static void trace(JSTracer* trc, JSObject* obj);
 
-  FinalizationGroupObject* groupUnbarriered() const;
+  FinalizationRegistryObject* registryUnbarriered() const;
 };
 
 // A vector of FinalizationRecordObjects.
 using FinalizationRecordVector =
     GCVector<HeapPtr<FinalizationRecordObject*>, 1, js::ZoneAllocPolicy>;
 
 // A JS object that wraps a FinalizationRecordVector. Used as the values in the
 // registration weakmap.
@@ -160,18 +160,18 @@ class FinalizationRecordVectorObject : p
 
   static void trace(JSTracer* trc, JSObject* obj);
   static void finalize(JSFreeOp* fop, JSObject* obj);
 };
 
 using FinalizationRecordSet =
     GCHashSet<HeapPtrObject, MovableCellHasher<HeapPtrObject>, ZoneAllocPolicy>;
 
-// The FinalizationGroup object itself.
-class FinalizationGroupObject : public NativeObject {
+// The FinalizationRegistry object itself.
+class FinalizationRegistryObject : public NativeObject {
   enum {
     CleanupCallbackSlot = 0,
     RegistrationsSlot,
     ActiveRecords,
     RecordsToBeCleanedUpSlot,
     IsQueuedForCleanupSlot,
     IsCleanupJobActiveSlot,
     SlotCount
@@ -188,65 +188,65 @@ class FinalizationGroupObject : public N
   bool isQueuedForCleanup() const;
   bool isCleanupJobActive() const;
 
   void queueRecordToBeCleanedUp(FinalizationRecordObject* record);
   void setQueuedForCleanup(bool value);
   void setCleanupJobActive(bool value);
 
   static bool cleanupQueuedRecords(JSContext* cx,
-                                   HandleFinalizationGroupObject group,
+                                   HandleFinalizationRegistryObject registry,
                                    HandleObject callback = nullptr);
 
  private:
   static const JSClassOps classOps_;
   static const ClassSpec classSpec_;
   static const JSFunctionSpec methods_[];
   static const JSPropertySpec properties_[];
 
   static bool construct(JSContext* cx, unsigned argc, Value* vp);
   static bool register_(JSContext* cx, unsigned argc, Value* vp);
   static bool unregister(JSContext* cx, unsigned argc, Value* vp);
   static bool cleanupSome(JSContext* cx, unsigned argc, Value* vp);
 
   static bool addRegistration(JSContext* cx,
-                              HandleFinalizationGroupObject group,
+                              HandleFinalizationRegistryObject registry,
                               HandleObject unregisterToken,
                               HandleFinalizationRecordObject record);
-  static void removeRegistrationOnError(HandleFinalizationGroupObject group,
-                                        HandleObject unregisterToken,
-                                        HandleFinalizationRecordObject record);
+  static void removeRegistrationOnError(
+      HandleFinalizationRegistryObject registry, HandleObject unregisterToken,
+      HandleFinalizationRecordObject record);
 
   static void trace(JSTracer* trc, JSObject* obj);
   static void finalize(JSFreeOp* fop, JSObject* obj);
 
   static bool hasRegisteredRecordsToBeCleanedUp(
-      HandleFinalizationGroupObject group);
+      HandleFinalizationRegistryObject registry);
 };
 
-// An iterator over a finalization group's queued held values. In the spec this
-// is called FinalizationGroupCleanupIterator.
+// An iterator over a finalization registry's queued held values. In the spec
+// this is called FinalizationRegistryCleanupIterator.
 class FinalizationIteratorObject : public NativeObject {
-  enum { FinalizationGroupSlot = 0, IndexSlot, SlotCount };
+  enum { FinalizationRegistrySlot = 0, IndexSlot, SlotCount };
 
  public:
   static const JSClass class_;
 
   static FinalizationIteratorObject* create(
-      JSContext* cx, HandleFinalizationGroupObject group);
+      JSContext* cx, HandleFinalizationRegistryObject registry);
 
-  FinalizationGroupObject* finalizationGroup() const;
+  FinalizationRegistryObject* finalizationRegistry() const;
   size_t index() const;
 
   void setIndex(size_t index);
-  void clearFinalizationGroup();
+  void clearFinalizationRegistry();
 
  private:
   friend class GlobalObject;
   static const JSFunctionSpec methods_[];
   static const JSPropertySpec properties_[];
 
   static bool next(JSContext* cx, unsigned argc, Value* vp);
 };
 
 }  // namespace js
 
-#endif /* builtin_FinalizationGroupObject_h */
+#endif /* builtin_FinalizationRegistryObject_h */
rename from js/src/gc/FinalizationGroup.cpp
rename to js/src/gc/FinalizationRegistry.cpp
--- a/js/src/gc/FinalizationGroup.cpp
+++ b/js/src/gc/FinalizationRegistry.cpp
@@ -1,30 +1,30 @@
 /* -*- 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/. */
 
 /*
- * Finalization group GC implementation.
+ * Finalization registry GC implementation.
  */
 
-#include "builtin/FinalizationGroupObject.h"
+#include "builtin/FinalizationRegistryObject.h"
 #include "gc/GCRuntime.h"
 #include "gc/Zone.h"
 
 #include "gc/PrivateIterators-inl.h"
 
 using namespace js;
 using namespace js::gc;
 
-bool GCRuntime::registerWithFinalizationGroup(JSContext* cx,
-                                              HandleObject target,
-                                              HandleObject record) {
+bool GCRuntime::registerWithFinalizationRegistry(JSContext* cx,
+                                                 HandleObject target,
+                                                 HandleObject record) {
   MOZ_ASSERT(!IsCrossCompartmentWrapper(target));
   MOZ_ASSERT(
       UncheckedUnwrapWithoutExpose(record)->is<FinalizationRecordObject>());
   MOZ_ASSERT(target->compartment() == record->compartment());
 
   auto& map = target->zone()->finalizationRecordMap();
   auto ptr = map.lookupForAdd(target);
   if (!ptr) {
@@ -35,80 +35,80 @@ bool GCRuntime::registerWithFinalization
   }
   if (!ptr->value().append(record)) {
     ReportOutOfMemory(cx);
     return false;
   }
   return true;
 }
 
-void GCRuntime::markFinalizationGroupRoots(JSTracer* trc) {
+void GCRuntime::markFinalizationRegistryRoots(JSTracer* trc) {
   // The held values for all finalization records store in zone maps are marked
-  // as roots. Finalization records store a finalization group as a weak pointer
-  // in a private value, which does not get marked.
+  // as roots. Finalization records store a finalization registry as a weak
+  // pointer in a private value, which does not get marked.
   for (GCZonesIter zone(this); !zone.done(); zone.next()) {
     Zone::FinalizationRecordMap& map = zone->finalizationRecordMap();
     for (Zone::FinalizationRecordMap::Enum e(map); !e.empty(); e.popFront()) {
       e.front().value().trace(trc);
     }
   }
 }
 
 static FinalizationRecordObject* UnwrapFinalizationRecord(JSObject* obj) {
   obj = UncheckedUnwrapWithoutExpose(obj);
   if (!obj->is<FinalizationRecordObject>()) {
     MOZ_ASSERT(JS_IsDeadWrapper(obj));
     // CCWs between the compartments have been nuked. The
-    // FinalizationGroup's callback doesn't run in this case.
+    // FinalizationRegistry's callback doesn't run in this case.
     return nullptr;
   }
   return &obj->as<FinalizationRecordObject>();
 }
 
-void GCRuntime::sweepFinalizationGroups(Zone* zone) {
-  // Sweep finalization group data and queue finalization records for cleanup
+void GCRuntime::sweepFinalizationRegistries(Zone* zone) {
+  // Sweep finalization registry data and queue finalization records for cleanup
   // for any entries whose target is dying and remove them from the map.
 
   Zone::FinalizationRecordMap& map = zone->finalizationRecordMap();
   for (Zone::FinalizationRecordMap::Enum e(map); !e.empty(); e.popFront()) {
     FinalizationRecordVector& records = e.front().value();
 
     // Update any pointers moved by the GC.
     records.sweep();
 
     // Sweep finalization records and remove records for:
     records.eraseIf([](JSObject* obj) {
       FinalizationRecordObject* record = UnwrapFinalizationRecord(obj);
       return !record ||              // Nuked CCW to record.
              !record->isActive() ||  // Unregistered record or dead finalization
-                                     // group in previous sweep group.
-             !record->sweep();       // Dead finalization group in this sweep
+                                     // registry in previous sweep group.
+             !record->sweep();       // Dead finalization registry in this sweep
                                      // group.
     });
 
     // Queue finalization records for targets that are dying.
     if (IsAboutToBeFinalized(&e.front().mutableKey())) {
       for (JSObject* obj : records) {
         FinalizationRecordObject* record = UnwrapFinalizationRecord(obj);
-        FinalizationGroupObject* group = record->groupDuringGC(this);
-        group->queueRecordToBeCleanedUp(record);
-        queueFinalizationGroupForCleanup(group);
+        FinalizationRegistryObject* registry = record->registryDuringGC(this);
+        registry->queueRecordToBeCleanedUp(record);
+        queueFinalizationRegistryForCleanup(registry);
       }
       e.removeFront();
     }
   }
 }
 
-void GCRuntime::queueFinalizationGroupForCleanup(
-    FinalizationGroupObject* group) {
+void GCRuntime::queueFinalizationRegistryForCleanup(
+    FinalizationRegistryObject* registry) {
   // Prod the embedding to call us back later to run the finalization callbacks.
-  if (!group->isQueuedForCleanup()) {
-    callHostCleanupFinalizationGroupCallback(group);
-    group->setQueuedForCleanup(true);
+  if (!registry->isQueuedForCleanup()) {
+    callHostCleanupFinalizationRegistryCallback(registry);
+    registry->setQueuedForCleanup(true);
   }
 }
 
-bool GCRuntime::cleanupQueuedFinalizationGroup(
-    JSContext* cx, HandleFinalizationGroupObject group) {
-  group->setQueuedForCleanup(false);
-  bool ok = FinalizationGroupObject::cleanupQueuedRecords(cx, group);
+bool GCRuntime::cleanupQueuedFinalizationRegistry(
+    JSContext* cx, HandleFinalizationRegistryObject registry) {
+  registry->setQueuedForCleanup(false);
+  bool ok = FinalizationRegistryObject::cleanupQueuedRecords(cx, registry);
   return ok;
 }
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -208,17 +208,17 @@
 #  include <sys/mman.h>
 #  include <unistd.h>
 #endif
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "jstypes.h"
 
-#include "builtin/FinalizationGroupObject.h"
+#include "builtin/FinalizationRegistryObject.h"
 #include "debugger/DebugAPI.h"
 #include "gc/FindSCCs.h"
 #include "gc/FreeOp.h"
 #include "gc/GCInternals.h"
 #include "gc/GCLock.h"
 #include "gc/GCTrace.h"
 #include "gc/Memory.h"
 #include "gc/ParallelWork.h"
@@ -1562,27 +1562,27 @@ void GCRuntime::removeFinalizeCallback(J
 
 void GCRuntime::callFinalizeCallbacks(JSFreeOp* fop,
                                       JSFinalizeStatus status) const {
   for (auto& p : finalizeCallbacks.ref()) {
     p.op(fop, status, p.data);
   }
 }
 
-void GCRuntime::setHostCleanupFinalizationGroupCallback(
-    JSHostCleanupFinalizationGroupCallback callback, void* data) {
-  hostCleanupFinalizationGroupCallback.ref() = {callback, data};
-}
-
-void GCRuntime::callHostCleanupFinalizationGroupCallback(
-    FinalizationGroupObject* group) {
+void GCRuntime::setHostCleanupFinalizationRegistryCallback(
+    JSHostCleanupFinalizationRegistryCallback callback, void* data) {
+  hostCleanupFinalizationRegistryCallback.ref() = {callback, data};
+}
+
+void GCRuntime::callHostCleanupFinalizationRegistryCallback(
+    FinalizationRegistryObject* registry) {
   JS::AutoSuppressGCAnalysis nogc;
-  const auto& callback = hostCleanupFinalizationGroupCallback.ref();
+  const auto& callback = hostCleanupFinalizationRegistryCallback.ref();
   if (callback.op) {
-    callback.op(group, callback.data);
+    callback.op(registry, callback.data);
   }
 }
 
 bool GCRuntime::addWeakPointerZonesCallback(JSWeakPointerZonesCallback callback,
                                             void* data) {
   return updateWeakPointerZonesCallbacks.ref().append(
       Callback<JSWeakPointerZonesCallback>(callback, data));
 }
@@ -2139,17 +2139,17 @@ void GCRuntime::sweepTypesAfterCompactin
   }
 
   zone->types.endSweep(rt);
 }
 
 void GCRuntime::sweepZoneAfterCompacting(MovingTracer* trc, Zone* zone) {
   MOZ_ASSERT(zone->isCollecting());
   sweepTypesAfterCompacting(zone);
-  sweepFinalizationGroups(zone);
+  sweepFinalizationRegistries(zone);
   zone->weakRefMap().sweep();
   zone->sweepWeakMaps();
   for (auto* cache : zone->weakCaches()) {
     cache->sweep();
   }
 
   if (jit::JitZone* jitZone = zone->jitZone()) {
     jitZone->traceWeak(trc);
@@ -4972,22 +4972,23 @@ void GCRuntime::sweepUniqueIds() {
 
 void GCRuntime::sweepWeakRefs() {
   for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) {
     AutoSetThreadIsSweeping threadIsSweeping(zone);
     zone->weakRefMap().sweep();
   }
 }
 
-void GCRuntime::sweepFinalizationGroupsOnMainThread() {
+void GCRuntime::sweepFinalizationRegistriesOnMainThread() {
   // This calls back into the browser which expects to be called from the main
   // thread.
-  gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::SWEEP_FINALIZATION_GROUPS);
+  gcstats::AutoPhase ap(stats(),
+                        gcstats::PhaseKind::SWEEP_FINALIZATION_REGISTRIES);
   for (SweepGroupZonesIter zone(this); !zone.done(); zone.next()) {
-    sweepFinalizationGroups(zone);
+    sweepFinalizationRegistries(zone);
   }
 }
 
 void GCRuntime::startTask(GCParallelTask& task, gcstats::PhaseKind phase,
                           AutoLockHelperThreadState& lock) {
   if (!CanUseExtraThreads()) {
     AutoUnlockHelperThreadState unlock(lock);
     gcstats::AutoPhase ap(stats(), phase);
@@ -5260,17 +5261,17 @@ IncrementalProgress GCRuntime::beginSwee
 
     for (auto& task : sweepCacheTasks) {
       startTask(task, PhaseKind::SWEEP_WEAK_CACHES, lock);
     }
 
     {
       AutoUnlockHelperThreadState unlock(lock);
       sweepJitDataOnMainThread(fop);
-      sweepFinalizationGroupsOnMainThread();
+      sweepFinalizationRegistriesOnMainThread();
     }
 
     for (auto& task : sweepCacheTasks) {
       joinTask(task, PhaseKind::SWEEP_WEAK_CACHES, lock);
     }
   }
 
   if (sweepingAtoms) {
--- a/js/src/gc/GCEnum.h
+++ b/js/src/gc/GCEnum.h
@@ -133,19 +133,19 @@ enum class ZealMode {
   _(FileObjectFile)                        \
   _(Debugger)                              \
   _(DebuggerFrameGeneratorInfo)            \
   _(DebuggerFrameIterData)                 \
   _(DebuggerOnStepHandler)                 \
   _(DebuggerOnPopHandler)                  \
   _(RealmInstrumentation)                  \
   _(ICUObject)                             \
-  _(FinalizationGroupRecordVector)         \
-  _(FinalizationGroupRecordSet)            \
-  _(FinalizationGroupRegistrations)        \
+  _(FinalizationRegistryRecordVector)      \
+  _(FinalizationRegistryRecordSet)         \
+  _(FinalizationRegistryRegistrations)     \
   _(FinalizationRecordVector)              \
   _(ZoneAllocPolicy)                       \
   _(SharedArrayRawBuffer)                  \
   _(XDRBufferElements)
 
 #define JS_FOR_EACH_MEMORY_USE(_)  \
   JS_FOR_EACH_PUBLIC_MEMORY_USE(_) \
   JS_FOR_EACH_INTERNAL_MEMORY_USE(_)
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -24,17 +24,17 @@
 #include "vm/AtomsTable.h"
 
 namespace js {
 
 class AutoAccessAtomsZone;
 class AutoLockGC;
 class AutoLockGCBgAlloc;
 class AutoLockHelperThreadState;
-class FinalizationGroupObject;
+class FinalizationRegistryObject;
 class VerifyPreTracer;
 class WeakRefObject;
 class ZoneAllocator;
 
 namespace gc {
 
 using BlackGrayEdgeVector = Vector<TenuredCell*, 0, SystemAllocPolicy>;
 using ZoneVector = Vector<JS::Zone*, 4, SystemAllocPolicy>;
@@ -414,36 +414,37 @@ class GCRuntime {
 
   void setGCCallback(JSGCCallback callback, void* data);
   void callGCCallback(JSGCStatus status, JS::GCReason reason) const;
   void setObjectsTenuredCallback(JSObjectsTenuredCallback callback, void* data);
   void callObjectsTenuredCallback();
   MOZ_MUST_USE bool addFinalizeCallback(JSFinalizeCallback callback,
                                         void* data);
   void removeFinalizeCallback(JSFinalizeCallback func);
-  void setHostCleanupFinalizationGroupCallback(
-      JSHostCleanupFinalizationGroupCallback callback, void* data);
-  void callHostCleanupFinalizationGroupCallback(FinalizationGroupObject* group);
+  void setHostCleanupFinalizationRegistryCallback(
+      JSHostCleanupFinalizationRegistryCallback callback, void* data);
+  void callHostCleanupFinalizationRegistryCallback(
+      FinalizationRegistryObject* registry);
   MOZ_MUST_USE bool addWeakPointerZonesCallback(
       JSWeakPointerZonesCallback callback, void* data);
   void removeWeakPointerZonesCallback(JSWeakPointerZonesCallback callback);
   MOZ_MUST_USE bool addWeakPointerCompartmentCallback(
       JSWeakPointerCompartmentCallback callback, void* data);
   void removeWeakPointerCompartmentCallback(
       JSWeakPointerCompartmentCallback callback);
   JS::GCSliceCallback setSliceCallback(JS::GCSliceCallback callback);
   JS::GCNurseryCollectionCallback setNurseryCollectionCallback(
       JS::GCNurseryCollectionCallback callback);
   JS::DoCycleCollectionCallback setDoCycleCollectionCallback(
       JS::DoCycleCollectionCallback callback);
 
-  bool registerWithFinalizationGroup(JSContext* cx, HandleObject target,
-                                     HandleObject record);
-  bool cleanupQueuedFinalizationGroup(JSContext* cx,
-                                      Handle<FinalizationGroupObject*> group);
+  bool registerWithFinalizationRegistry(JSContext* cx, HandleObject target,
+                                        HandleObject record);
+  bool cleanupQueuedFinalizationRegistry(
+      JSContext* cx, Handle<FinalizationRegistryObject*> registry);
 
   void setFullCompartmentChecks(bool enable);
 
   JS::Zone* getCurrentSweepGroup() { return currentSweepGroup; }
   unsigned getCurrentSweepGroupIndex() {
     return state() == State::Sweep ? sweepGroupIndex : 0;
   }
 
@@ -684,17 +685,17 @@ class GCRuntime {
   void purgeShapeCachesForShrinkingGC();
   void purgeSourceURLsForShrinkingGC();
   void traceRuntimeForMajorGC(JSTracer* trc, AutoGCSession& session);
   void traceRuntimeAtoms(JSTracer* trc, const AutoAccessAtomsZone& atomsAccess);
   void traceKeptAtoms(JSTracer* trc);
   void traceRuntimeCommon(JSTracer* trc, TraceOrMarkRuntime traceOrMark);
   void traceEmbeddingBlackRoots(JSTracer* trc);
   void traceEmbeddingGrayRoots(JSTracer* trc);
-  void markFinalizationGroupRoots(JSTracer* trc);
+  void markFinalizationRegistryRoots(JSTracer* trc);
   void checkNoRuntimeRoots(AutoGCSession& session);
   void maybeDoCycleCollection();
   void findDeadCompartments();
 
   friend class SweepMarkTask;
   IncrementalProgress markUntilBudgetExhausted(SliceBudget& sliceBudget,
                                                gcstats::PhaseKind phase);
   IncrementalProgress markUntilBudgetExhausted(SliceBudget& sliceBudget);
@@ -724,19 +725,20 @@ class GCRuntime {
   void sweepObjectGroups();
   void sweepMisc();
   void sweepCompressionTasks();
   void sweepLazyScripts();
   void sweepWeakMaps();
   void sweepUniqueIds();
   void sweepDebuggerOnMainThread(JSFreeOp* fop);
   void sweepJitDataOnMainThread(JSFreeOp* fop);
-  void sweepFinalizationGroupsOnMainThread();
-  void sweepFinalizationGroups(Zone* zone);
-  void queueFinalizationGroupForCleanup(FinalizationGroupObject* group);
+  void sweepFinalizationRegistriesOnMainThread();
+  void sweepFinalizationRegistries(Zone* zone);
+  void queueFinalizationRegistryForCleanup(
+      FinalizationRegistryObject* registry);
   void sweepWeakRefs();
   IncrementalProgress endSweepingSweepGroup(JSFreeOp* fop, SliceBudget& budget);
   IncrementalProgress performSweepActions(SliceBudget& sliceBudget);
   IncrementalProgress sweepTypeInformation(JSFreeOp* fop, SliceBudget& budget);
   IncrementalProgress releaseSweptEmptyArenas(JSFreeOp* fop,
                                               SliceBudget& budget);
   void startSweepingAtomsTable();
   IncrementalProgress sweepAtomsTable(JSFreeOp* fop, SliceBudget& budget);
@@ -1093,18 +1095,18 @@ class GCRuntime {
 
   MainThreadData<uint32_t> gcCallbackDepth;
 
   MainThreadData<Callback<JSGCCallback>> gcCallback;
   MainThreadData<Callback<JS::DoCycleCollectionCallback>>
       gcDoCycleCollectionCallback;
   MainThreadData<Callback<JSObjectsTenuredCallback>> tenuredCallback;
   MainThreadData<CallbackVector<JSFinalizeCallback>> finalizeCallbacks;
-  MainThreadOrGCTaskData<Callback<JSHostCleanupFinalizationGroupCallback>>
-      hostCleanupFinalizationGroupCallback;
+  MainThreadOrGCTaskData<Callback<JSHostCleanupFinalizationRegistryCallback>>
+      hostCleanupFinalizationRegistryCallback;
   MainThreadData<CallbackVector<JSWeakPointerZonesCallback>>
       updateWeakPointerZonesCallbacks;
   MainThreadData<CallbackVector<JSWeakPointerCompartmentCallback>>
       updateWeakPointerCompartmentCallbacks;
 
   /*
    * The trace operations to trace embedding-specific GC roots. One is for
    * tracing through black roots and the other is for tracing through gray
--- a/js/src/gc/GenerateStatsPhases.py
+++ b/js/src/gc/GenerateStatsPhases.py
@@ -137,17 +137,17 @@ PhaseKindGraphRoots = [
             PhaseKind("SWEEP_CC_WRAPPER", "Sweep Cross Compartment Wrappers", 23),
             PhaseKind("SWEEP_BASE_SHAPE", "Sweep Base Shapes", 24),
             PhaseKind("SWEEP_INITIAL_SHAPE", "Sweep Initial Shapes", 25),
             PhaseKind("SWEEP_TYPE_OBJECT", "Sweep Type Objects", 26),
             PhaseKind("SWEEP_REGEXP", "Sweep Regexps", 28),
             PhaseKind("SWEEP_COMPRESSION", "Sweep Compression Tasks", 62),
             PhaseKind("SWEEP_WEAKMAPS", "Sweep WeakMaps", 63),
             PhaseKind("SWEEP_UNIQUEIDS", "Sweep Unique IDs", 64),
-            PhaseKind("SWEEP_FINALIZATION_GROUPS", "Sweep FinalizationGroups", 74, [
+            PhaseKind("SWEEP_FINALIZATION_REGISTRIES", "Sweep FinalizationRegistries", 74, [
                 UnmarkGrayPhaseKind
             ]),
             PhaseKind("SWEEP_WEAKREFS", "Sweep WeakRefs", 75),
             PhaseKind("SWEEP_JIT_DATA", "Sweep JIT Data", 65),
             PhaseKind("SWEEP_WEAK_CACHES", "Sweep Weak Caches", 66),
             PhaseKind("SWEEP_MISC", "Sweep Miscellaneous", 29),
             PhaseKind("SWEEP_TYPES", "Sweep type information", 30, [
                 PhaseKind("SWEEP_TYPES_BEGIN", "Sweep type tables and compilations", 31),
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -280,17 +280,17 @@ void js::gc::GCRuntime::traceRuntimeForM
   {
     // Trace incoming cross compartment edges from uncollected compartments,
     // skipping gray edges which are traced later.
     gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::MARK_CCWS);
     Compartment::traceIncomingCrossCompartmentEdgesForZoneGC(
         trc, Compartment::NonGrayEdges);
   }
 
-  markFinalizationGroupRoots(trc);
+  markFinalizationRegistryRoots(trc);
 
   traceRuntimeCommon(trc, MarkRuntime);
 }
 
 void js::gc::GCRuntime::traceRuntimeForMinorGC(JSTracer* trc,
                                                AutoGCSession& session) {
   MOZ_ASSERT(!TlsContext.get()->suppressGC);
 
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -314,19 +314,19 @@ class Zone : public js::ZoneAllocator, p
   // InitialShapeProto.
   js::ZoneData<js::InitialShapeSet> initialShapes_;
 
   // List of shapes that may contain nursery pointers.
   using NurseryShapeVector =
       js::Vector<js::AccessorShape*, 0, js::SystemAllocPolicy>;
   js::ZoneData<NurseryShapeVector> nurseryShapes_;
 
-  // A map from finalization group targets to a list of finalization records
-  // representing groups that the target is registered with and their associated
-  // held values.
+  // A map from finalization registry targets to a list of finalization records
+  // representing registries that the target is registered with and their
+  // associated held values.
   using FinalizationRecordMap =
       GCHashMap<js::HeapPtrObject, js::gc::FinalizationRecordVector,
                 js::MovableCellHasher<js::HeapPtrObject>, js::ZoneAllocPolicy>;
   js::ZoneOrGCTaskData<FinalizationRecordMap> finalizationRecordMap_;
 
   js::ZoneOrGCTaskData<js::jit::JitZone*> jitZone_;
 
   js::MainThreadData<bool> gcScheduled_;
--- a/js/src/gc/moz.build
+++ b/js/src/gc/moz.build
@@ -21,17 +21,17 @@ GeneratedFile('StatsPhasesGenerated.h',
               script='GenerateStatsPhases.py', entry_point='generateHeader')
 GeneratedFile('StatsPhasesGenerated.inc',
               script='GenerateStatsPhases.py', entry_point='generateCpp')
 
 UNIFIED_SOURCES += [
     'Allocator.cpp',
     'AtomMarking.cpp',
     'Barrier.cpp',
-    'FinalizationGroup.cpp',
+    'FinalizationRegistry.cpp',
     'GC.cpp',
     'GCParallelTask.cpp',
     'GCTrace.cpp',
     'Marking.cpp',
     'Memory.cpp',
     'Nursery.cpp',
     'PublicIterators.cpp',
     'RootMarking.cpp',
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -724,18 +724,18 @@ MSG_DEF(JSMSG_BIGINT_DIVISION_BY_ZERO, 0
 MSG_DEF(JSMSG_BIGINT_NEGATIVE_EXPONENT, 0, JSEXN_RANGEERR, "BigInt negative exponent")
 MSG_DEF(JSMSG_BIGINT_INVALID_SYNTAX, 0, JSEXN_SYNTAXERR, "invalid BigInt syntax")
 MSG_DEF(JSMSG_BIGINT_NOT_SERIALIZABLE, 0, JSEXN_TYPEERR, "BigInt value can't be serialized in JSON")
 MSG_DEF(JSMSG_SC_BIGINT_DISABLED, 0, JSEXN_ERR, "BigInt not cloned - feature disabled in receiver")
 
 // BinAST
 MSG_DEF(JSMSG_BINAST,                                    1, JSEXN_SYNTAXERR, "BinAST Parsing Error: {0}")
 
-// FinalizationGroup
-MSG_DEF(JSMSG_NOT_A_FINALIZATION_GROUP,                  1, JSEXN_TYPEERR, "{0} is not a FinalizationGroup")
-MSG_DEF(JSMSG_NOT_A_FINALIZATION_ITERATOR,               1, JSEXN_TYPEERR, "{0} is not a FinalizationGroupCleanupIterator")
-MSG_DEF(JSMSG_BAD_HELD_VALUE,                            0, JSEXN_TYPEERR, "The heldValue parameter passed to FinalizationGroup.register must not be the same as the target parameter")
+// FinalizationRegistry
+MSG_DEF(JSMSG_NOT_A_FINALIZATION_REGISTRY,               1, JSEXN_TYPEERR, "{0} is not a FinalizationRegistry")
+MSG_DEF(JSMSG_NOT_A_FINALIZATION_ITERATOR,               1, JSEXN_TYPEERR, "{0} is not a FinalizationRegistryCleanupIterator")
+MSG_DEF(JSMSG_BAD_HELD_VALUE,                            0, JSEXN_TYPEERR, "The heldValue parameter passed to FinalizationRegistry.register must not be the same as the target parameter")
 MSG_DEF(JSMSG_BAD_UNREGISTER_TOKEN,                      1, JSEXN_TYPEERR, "Invalid unregister token passed to {0}")
-MSG_DEF(JSMSG_STALE_FINALIZATION_GROUP_ITERATOR,         0, JSEXN_TYPEERR, "Can't use stale finalization group iterator")
-MSG_DEF(JSMSG_BAD_CLEANUP_STATE,                         0, JSEXN_TYPEERR, "Can't call FinalizeGroup.cleanupSome while cleanup is in progress")
+MSG_DEF(JSMSG_STALE_FINALIZATION_REGISTRY_ITERATOR,      0, JSEXN_TYPEERR, "Can't use stale finalization registry iterator")
+MSG_DEF(JSMSG_BAD_CLEANUP_STATE,                         0, JSEXN_TYPEERR, "Can't call FinalizeRegistry.cleanupSome while cleanup is in progress")
 
 // WeakRef
 MSG_DEF(JSMSG_NOT_A_WEAK_REF,                            1, JSEXN_TYPEERR, "{0} is not a WeakRef")
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -28,17 +28,17 @@
 #include "jsmath.h"
 #include "jsnum.h"
 #include "jstypes.h"
 
 #include "builtin/Array.h"
 #include "builtin/AtomicsObject.h"
 #include "builtin/Boolean.h"
 #include "builtin/Eval.h"
-#include "builtin/FinalizationGroupObject.h"
+#include "builtin/FinalizationRegistryObject.h"
 #include "builtin/JSON.h"
 #include "builtin/MapObject.h"
 #include "builtin/Promise.h"
 #include "builtin/Stream.h"
 #include "builtin/Symbol.h"
 #ifdef JS_HAS_TYPED_OBJECTS
 #  include "builtin/TypedObject.h"
 #endif
@@ -1336,29 +1336,29 @@ JS_PUBLIC_API bool JS_AddFinalizeCallbac
   return cx->runtime()->gc.addFinalizeCallback(cb, data);
 }
 
 JS_PUBLIC_API void JS_RemoveFinalizeCallback(JSContext* cx,
                                              JSFinalizeCallback cb) {
   cx->runtime()->gc.removeFinalizeCallback(cb);
 }
 
-JS_PUBLIC_API void JS::SetHostCleanupFinalizationGroupCallback(
-    JSContext* cx, JSHostCleanupFinalizationGroupCallback cb, void* data) {
+JS_PUBLIC_API void JS::SetHostCleanupFinalizationRegistryCallback(
+    JSContext* cx, JSHostCleanupFinalizationRegistryCallback cb, void* data) {
   AssertHeapIsIdle();
-  cx->runtime()->gc.setHostCleanupFinalizationGroupCallback(cb, data);
-}
-
-JS_PUBLIC_API bool JS::CleanupQueuedFinalizationGroup(JSContext* cx,
-                                                      HandleObject group) {
+  cx->runtime()->gc.setHostCleanupFinalizationRegistryCallback(cb, data);
+}
+
+JS_PUBLIC_API bool JS::CleanupQueuedFinalizationRegistry(
+    JSContext* cx, HandleObject registry) {
   AssertHeapIsIdle();
   CHECK_THREAD(cx);
-  cx->check(group);
-  return cx->runtime()->gc.cleanupQueuedFinalizationGroup(
-      cx, group.as<FinalizationGroupObject>());
+  cx->check(registry);
+  return cx->runtime()->gc.cleanupQueuedFinalizationRegistry(
+      cx, registry.as<FinalizationRegistryObject>());
 }
 
 JS_PUBLIC_API void JS::ClearKeptObjects(JSContext* cx) {
   gc::GCRuntime* gc = &cx->runtime()->gc;
 
   for (ZonesIter zone(gc, ZoneSelector::WithAtoms); !zone.done(); zone.next()) {
     zone->clearKeptObjects();
   }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3134,21 +3134,21 @@ extern JS_PUBLIC_API bool IsMaybeWrapped
 
 /**
  * Return true iff the given object is a SavedFrame object and not the
  * SavedFrame.prototype object.
  */
 extern JS_PUBLIC_API bool IsUnwrappedSavedFrame(JSObject* obj);
 
 /**
- * Clean up a finalization group in response to the engine calling the
- * HostCleanupFinalizationGroup callback.
+ * Clean up a finalization registry in response to the engine calling the
+ * HostCleanupFinalizationRegistry callback.
  */
-extern JS_PUBLIC_API bool CleanupQueuedFinalizationGroup(JSContext* cx,
-                                                         HandleObject group);
+extern JS_PUBLIC_API bool CleanupQueuedFinalizationRegistry(
+    JSContext* cx, HandleObject registry);
 
 } /* namespace JS */
 
 namespace js {
 
 /**
  * Hint that we expect a crash. Currently, the only thing that cares is the
  * breakpad injector, which (if loaded) will suppress minidump generation.
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -214,17 +214,17 @@ EXPORTS.js.experimental += [
 
 UNIFIED_SOURCES += [
     'builtin/Array.cpp',
     'builtin/AtomicsObject.cpp',
     'builtin/BigInt.cpp',
     'builtin/Boolean.cpp',
     'builtin/DataViewObject.cpp',
     'builtin/Eval.cpp',
-    'builtin/FinalizationGroupObject.cpp',
+    'builtin/FinalizationRegistryObject.cpp',
     'builtin/JSON.cpp',
     'builtin/MapObject.cpp',
     'builtin/ModuleObject.cpp',
     'builtin/Object.cpp',
     'builtin/Profilers.cpp',
     'builtin/Promise.cpp',
     'builtin/Reflect.cpp',
     'builtin/ReflectParse.cpp',
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -646,17 +646,17 @@ ShellContext::ShellContext(JSContext* cx
       unhandledRejectedPromises(cx),
       watchdogLock(mutexid::ShellContextWatchdog),
       exitCode(0),
       quitting(false),
       readLineBufPos(0),
       errFilePtr(nullptr),
       outFilePtr(nullptr),
       offThreadMonitor(mutexid::ShellOffThreadState),
-      finalizationGroupsToCleanUp(cx) {}
+      finalizationRegistriesToCleanUp(cx) {}
 
 ShellContext::~ShellContext() { MOZ_ASSERT(offThreadJobs.empty()); }
 
 ShellContext* js::shell::GetShellContext(JSContext* cx) {
   ShellContext* sc = static_cast<ShellContext*>(JS_GetContextPrivate(cx));
   MOZ_ASSERT(sc);
   return sc;
 }
@@ -1023,45 +1023,46 @@ static MOZ_MUST_USE bool RunModule(JSCon
 
   JS::AutoValueArray<1> args(cx);
   args[0].setString(path);
 
   RootedValue value(cx);
   return JS_CallFunction(cx, nullptr, importFun, args, &value);
 }
 
-static void ShellCleanupFinalizationGroupCallback(JSObject* group, void* data) {
+static void ShellCleanupFinalizationRegistryCallback(JSObject* registry,
+                                                     void* data) {
   // In the browser this queues a task. Shell jobs correspond to microtasks so
   // we arrange for cleanup to happen after all jobs/microtasks have run.
   auto sc = static_cast<ShellContext*>(data);
   AutoEnterOOMUnsafeRegion oomUnsafe;
-  if (!sc->finalizationGroupsToCleanUp.append(group)) {
-    oomUnsafe.crash("ShellCleanupFinalizationGroupCallback");
-  }
-}
-
-// Run any FinalizationGroup cleanup tasks and return whether any ran.
-static bool MaybeRunFinalizationGroupCleanupTasks(JSContext* cx) {
+  if (!sc->finalizationRegistriesToCleanUp.append(registry)) {
+    oomUnsafe.crash("ShellCleanupFinalizationRegistryCallback");
+  }
+}
+
+// Run any FinalizationRegistry cleanup tasks and return whether any ran.
+static bool MaybeRunFinalizationRegistryCleanupTasks(JSContext* cx) {
   ShellContext* sc = GetShellContext(cx);
   MOZ_ASSERT(!sc->quitting);
 
-  Rooted<ShellContext::ObjectVector> groups(cx);
-  std::swap(groups.get(), sc->finalizationGroupsToCleanUp.get());
+  Rooted<ShellContext::ObjectVector> registries(cx);
+  std::swap(registries.get(), sc->finalizationRegistriesToCleanUp.get());
 
   bool ranTasks = false;
 
-  RootedObject group(cx);
-  for (const auto& g : groups) {
-    group = g;
-
-    AutoRealm ar(cx, group);
+  RootedObject registry(cx);
+  for (const auto& r : registries) {
+    registry = r;
+
+    AutoRealm ar(cx, registry);
 
     {
       AutoReportException are(cx);
-      mozilla::Unused << JS::CleanupQueuedFinalizationGroup(cx, group);
+      mozilla::Unused << JS::CleanupQueuedFinalizationRegistry(cx, registry);
     }
 
     ranTasks = true;
 
     if (sc->quitting) {
       break;
     }
   }
@@ -1091,18 +1092,18 @@ static void RunShellJobs(JSContext* cx) 
 
   while (true) {
     // Run microtasks.
     js::RunJobs(cx);
     if (sc->quitting) {
       return;
     }
 
-    // Run tasks (only finalization group clean tasks are possible).
-    bool ranTasks = MaybeRunFinalizationGroupCleanupTasks(cx);
+    // Run tasks (only finalization registry clean tasks are possible).
+    bool ranTasks = MaybeRunFinalizationRegistryCleanupTasks(cx);
     if (!ranTasks) {
       break;
     }
   }
 }
 
 static bool DrainJobQueue(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
@@ -4116,18 +4117,18 @@ static void WorkerMain(WorkerInput* inpu
   js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
   JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
   JS_SetDestroyCompartmentCallback(cx, DestroyShellCompartmentPrivate);
 
   js::SetWindowProxyClass(cx, &ShellWindowProxyClass);
 
   js::UseInternalJobQueues(cx);
 
-  JS::SetHostCleanupFinalizationGroupCallback(
-      cx, ShellCleanupFinalizationGroupCallback, sc);
+  JS::SetHostCleanupFinalizationRegistryCallback(
+      cx, ShellCleanupFinalizationRegistryCallback, sc);
 
   if (!JS::InitSelfHostedCode(cx)) {
     return;
   }
 
   EnvironmentPreparer environmentPreparer(cx);
 
   do {
@@ -11530,18 +11531,18 @@ int main(int argc, char** argv, char** e
       cx, ForwardingPromiseRejectionTrackerCallback);
 
   JS_SetNativeStackQuota(cx, gMaxStackSize);
 
   JS::dbg::SetDebuggerMallocSizeOf(cx, moz_malloc_size_of);
 
   js::UseInternalJobQueues(cx);
 
-  JS::SetHostCleanupFinalizationGroupCallback(
-      cx, ShellCleanupFinalizationGroupCallback, sc.get());
+  JS::SetHostCleanupFinalizationRegistryCallback(
+      cx, ShellCleanupFinalizationRegistryCallback, sc.get());
 
   auto shutdownShellThreads = MakeScopeExit([cx] {
     KillWatchdog(cx);
     KillWorkerThreads(cx);
     DestructSharedObjectMailbox();
     CancelOffThreadJobsForRuntime(cx);
   });
 
--- a/js/src/shell/jsshell.h
+++ b/js/src/shell/jsshell.h
@@ -228,19 +228,19 @@ struct ShellContext {
   JS::UniqueChars moduleLoadPath;
 
   UniquePtr<MarkBitObservers> markObservers;
 
   // Off-thread parse state.
   js::Monitor offThreadMonitor;
   Vector<OffThreadJob*, 0, SystemAllocPolicy> offThreadJobs;
 
-  // Queued finalization group cleanup jobs.
+  // Queued finalization registry cleanup jobs.
   using ObjectVector = GCVector<JSObject*, 0, SystemAllocPolicy>;
-  JS::PersistentRooted<ObjectVector> finalizationGroupsToCleanUp;
+  JS::PersistentRooted<ObjectVector> finalizationRegistriesToCleanUp;
 };
 
 extern ShellContext* GetShellContext(JSContext* cx);
 
 extern MOZ_MUST_USE bool PrintStackTrace(JSContext* cx,
                                          JS::Handle<JSObject*> stackObj);
 
 } /* namespace shell */
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -19,17 +19,17 @@
 #  include "builtin/intl/Collator.h"
 #  include "builtin/intl/DateTimeFormat.h"
 #  include "builtin/intl/ListFormat.h"
 #  include "builtin/intl/Locale.h"
 #  include "builtin/intl/NumberFormat.h"
 #  include "builtin/intl/PluralRules.h"
 #  include "builtin/intl/RelativeTimeFormat.h"
 #endif
-#include "builtin/FinalizationGroupObject.h"
+#include "builtin/FinalizationRegistryObject.h"
 #include "builtin/MapObject.h"
 #include "builtin/ModuleObject.h"
 #include "builtin/Object.h"
 #include "builtin/RegExp.h"
 #include "builtin/SelfHostingDefines.h"
 #include "builtin/Stream.h"
 #include "builtin/streams/QueueingStrategies.h"  // js::{ByteLength,Count}QueueingStrategy
 #include "builtin/streams/ReadableStream.h"  // js::ReadableStream
@@ -200,17 +200,17 @@ bool GlobalObject::skipDeselectedConstru
     }
 
     // Return true if the given constructor has been disabled at run-time.
     case JSProto_Atomics:
     case JSProto_SharedArrayBuffer:
       return !cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled();
 
     case JSProto_WeakRef:
-    case JSProto_FinalizationGroup:
+    case JSProto_FinalizationRegistry:
       return !cx->realm()->creationOptions().getWeakRefsEnabled();
 
     case JSProto_AggregateError:
 #ifndef NIGHTLY_BUILD
       return true;
 #else
       return false;
 #endif
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -841,17 +841,17 @@ class GlobalObject : public NativeObject
   static bool initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
   static bool initRequestedModuleProto(JSContext* cx,
                                        Handle<GlobalObject*> global);
 
   // Implemented in builtin/TypedObject.cpp
   static bool initTypedObjectModule(JSContext* cx,
                                     Handle<GlobalObject*> global);
 
-  // Implemented in builtin/FinalizationGroup.cpp
+  // Implemented in builtin/FinalizationRegistry.cpp
   static bool initFinalizationIteratorProto(JSContext* cx,
                                             Handle<GlobalObject*> global);
 
   static bool initStandardClasses(JSContext* cx, Handle<GlobalObject*> global);
   static bool initSelfHostingBuiltins(JSContext* cx,
                                       Handle<GlobalObject*> global,
                                       const JSFunctionSpec* builtins);
 
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -4424,17 +4424,17 @@
 # Use better error message when accessing property of null or undefined.
 - name: javascript.options.property_error_message_fix
   type: RelaxedAtomicBool
   value: @IS_NOT_RELEASE_OR_BETA@
   mirror: always
 
 #ifdef NIGHTLY_BUILD
   # Experimental support for weak references in JavaScript (WeakRef and
-  # FinalizationGroup).
+  # FinalizationRegistry).
 - name: javascript.options.experimental.weakrefs
   type: RelaxedAtomicBool
   value: false
   mirror: always
 #endif
 
 # The amount of time we wait between a request to GC (due to leaving a page) and doing the actual GC, in ms.
 - name: javascript.options.gc_delay
--- a/xpcom/base/CycleCollectedJSContext.cpp
+++ b/xpcom/base/CycleCollectedJSContext.cpp
@@ -74,18 +74,18 @@ CycleCollectedJSContext::CycleCollectedJ
 
 CycleCollectedJSContext::~CycleCollectedJSContext() {
   MOZ_COUNT_DTOR(CycleCollectedJSContext);
   // If the allocation failed, here we are.
   if (!mJSContext) {
     return;
   }
 
-  JS::SetHostCleanupFinalizationGroupCallback(mJSContext, nullptr, nullptr);
-  mFinalizationGroupsToCleanUp.reset();
+  JS::SetHostCleanupFinalizationRegistryCallback(mJSContext, nullptr, nullptr);
+  mFinalizationRegistriesToCleanUp.reset();
 
   JS_SetContextPrivate(mJSContext, nullptr);
 
   mRuntime->SetContext(nullptr);
   mRuntime->Shutdown(mJSContext);
 
   // Last chance to process any events.
   CleanupIDBTransactions(mBaseRecursionDepth);
@@ -144,19 +144,19 @@ nsresult CycleCollectedJSContext::Initia
                                          PromiseRejectionTrackerCallback, this);
   mUncaughtRejections.init(mJSContext,
                            JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(
                                js::SystemAllocPolicy()));
   mConsumedRejections.init(mJSContext,
                            JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(
                                js::SystemAllocPolicy()));
 
-  mFinalizationGroupsToCleanUp.init(mJSContext);
-  JS::SetHostCleanupFinalizationGroupCallback(
-      mJSContext, CleanupFinalizationGroupCallback, this);
+  mFinalizationRegistriesToCleanUp.init(mJSContext);
+  JS::SetHostCleanupFinalizationRegistryCallback(
+      mJSContext, CleanupFinalizationRegistryCallback, this);
 
   // Cast to PerThreadAtomCache for dom::GetAtomCache(JSContext*).
   JS_SetContextPrivate(mJSContext, static_cast<PerThreadAtomCache*>(this));
 
   nsCycleCollector_registerJSContext(this);
 
   return NS_OK;
 }
@@ -736,59 +736,61 @@ nsresult CycleCollectedJSContext::Notify
     }
 
     JS::RootedObject promiseObj(mCx->RootingCx(), promise->PromiseObj());
     mCx->mPendingUnhandledRejections.Remove(JS::GetPromiseID(promiseObj));
   }
   return NS_OK;
 }
 
-class CleanupFinalizationGroupsRunnable : public CancelableRunnable {
+class CleanupFinalizationRegistriesRunnable : public CancelableRunnable {
  public:
-  explicit CleanupFinalizationGroupsRunnable(CycleCollectedJSContext* aContext)
-      : CancelableRunnable("CleanupFinalizationGroupsRunnable"),
+  explicit CleanupFinalizationRegistriesRunnable(
+      CycleCollectedJSContext* aContext)
+      : CancelableRunnable("CleanupFinalizationRegistriesRunnable"),
         mContext(aContext) {}
   NS_DECL_NSIRUNNABLE
  private:
   CycleCollectedJSContext* mContext;
 };
 
 NS_IMETHODIMP
-CleanupFinalizationGroupsRunnable::Run() {
-  if (mContext->mFinalizationGroupsToCleanUp.empty()) {
+CleanupFinalizationRegistriesRunnable::Run() {
+  if (mContext->mFinalizationRegistriesToCleanUp.empty()) {
     return NS_OK;
   }
 
   JS::RootingContext* cx = mContext->RootingCx();
 
-  JS::Rooted<CycleCollectedJSContext::ObjectVector> groups(cx);
-  std::swap(groups.get(), mContext->mFinalizationGroupsToCleanUp.get());
+  JS::Rooted<CycleCollectedJSContext::ObjectVector> registries(cx);
+  std::swap(registries.get(), mContext->mFinalizationRegistriesToCleanUp.get());
 
-  JS::Rooted<JSObject*> group(cx);
-  for (const auto& g : groups) {
-    group = g;
+  JS::Rooted<JSObject*> registry(cx);
+  for (const auto& r : registries) {
+    registry = r;
 
-    AutoEntryScript aes(group, "cleanupFinalizationGroup");
-    mozilla::Unused << JS::CleanupQueuedFinalizationGroup(aes.cx(), group);
+    AutoEntryScript aes(registry, "cleanupFinalizationRegistry");
+    mozilla::Unused << JS::CleanupQueuedFinalizationRegistry(aes.cx(),
+                                                             registry);
   }
 
   return NS_OK;
 }
 
 /* static */
-void CycleCollectedJSContext::CleanupFinalizationGroupCallback(JSObject* aGroup,
-                                                               void* aData) {
+void CycleCollectedJSContext::CleanupFinalizationRegistryCallback(
+    JSObject* aRegistry, void* aData) {
   CycleCollectedJSContext* ccjs = static_cast<CycleCollectedJSContext*>(aData);
-  ccjs->QueueFinalizationGroupForCleanup(aGroup);
+  ccjs->QueueFinalizationRegistryForCleanup(aRegistry);
 }
 
-void CycleCollectedJSContext::QueueFinalizationGroupForCleanup(
-    JSObject* aGroup) {
-  bool firstGroup = mFinalizationGroupsToCleanUp.empty();
-  MOZ_ALWAYS_TRUE(mFinalizationGroupsToCleanUp.append(aGroup));
-  if (firstGroup) {
-    RefPtr<CleanupFinalizationGroupsRunnable> cleanup =
-        new CleanupFinalizationGroupsRunnable(this);
+void CycleCollectedJSContext::QueueFinalizationRegistryForCleanup(
+    JSObject* aRegistry) {
+  bool firstRegistry = mFinalizationRegistriesToCleanUp.empty();
+  MOZ_ALWAYS_TRUE(mFinalizationRegistriesToCleanUp.append(aRegistry));
+  if (firstRegistry) {
+    RefPtr<CleanupFinalizationRegistriesRunnable> cleanup =
+        new CleanupFinalizationRegistriesRunnable(this);
     NS_DispatchToCurrentThread(cleanup.forget());
   }
 }
 
 }  // namespace mozilla
--- a/xpcom/base/CycleCollectedJSContext.h
+++ b/xpcom/base/CycleCollectedJSContext.h
@@ -257,18 +257,19 @@ class CycleCollectedJSContext : dom::Per
   // headers.  The caller presumably knows this can run script (like everything
   // in SpiderMonkey!) and will deal.
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
   void runJobs(JSContext* cx) override;
   bool empty() const override;
   class SavedMicroTaskQueue;
   js::UniquePtr<SavedJobQueue> saveJobQueue(JSContext*) override;
 
-  static void CleanupFinalizationGroupCallback(JSObject* aGroup, void* aData);
-  void QueueFinalizationGroupForCleanup(JSObject* aGroup);
+  static void CleanupFinalizationRegistryCallback(JSObject* aRegistry,
+                                                  void* aData);
+  void QueueFinalizationRegistryForCleanup(JSObject* aRegistry);
 
  private:
   CycleCollectedJSRuntime* mRuntime;
 
   JSContext* mJSContext;
 
   nsCOMPtr<dom::Exception> mPendingException;
   nsThread* mOwningThread;  // Manual refcounting to avoid include hell.
@@ -334,24 +335,24 @@ class CycleCollectedJSContext : dom::Per
 
     nsresult Cancel() final;
 
    private:
     CycleCollectedJSContext* mCx;
     PromiseArray mUnhandledRejections;
   };
 
-  // Support for JS FinalizationGroup objects.
+  // Support for JS FinalizationRegistry objects.
   //
   // These allow a JS callback to be registered that is called when an object
   // dies. The browser part of the implementation keeps a vector of
-  // FinalizationGroups with pending callbacks here.
-  friend class CleanupFinalizationGroupsRunnable;
+  // FinalizationRegistries with pending callbacks here.
+  friend class CleanupFinalizationRegistriesRunnable;
   using ObjectVector = JS::GCVector<JSObject*, 0, InfallibleAllocPolicy>;
-  JS::PersistentRooted<ObjectVector> mFinalizationGroupsToCleanUp;
+  JS::PersistentRooted<ObjectVector> mFinalizationRegistriesToCleanUp;
 };
 
 class MOZ_STACK_CLASS nsAutoMicroTask {
  public:
   nsAutoMicroTask() {
     CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
     if (ccjs) {
       ccjs->EnterMicroTask();