Merge inbound to mozilla-central. a=merge
authorBrindusan Cristian <cbrindusan@mozilla.com>
Sun, 24 Jun 2018 00:45:20 +0300
changeset 480185 5dc06b87c88ef4707aeebdd9f8b8c6935edda0c4
parent 480184 61764577fd691ff8bc005959c185c2ddd671d68d (current diff)
parent 480183 b00a4031dbe4d29acb5358e60f509a926caa4753 (diff)
child 480186 289da21fb17c45441c83177520aee4f67f7f5fc3
child 480196 c14a08c8e6a6caafba7c204f6de1de562052e89a
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone62.0a1
first release with
nightly linux32
5dc06b87c88e / 62.0a1 / 20180623220115 / files
nightly linux64
5dc06b87c88e / 62.0a1 / 20180623220115 / files
nightly mac
5dc06b87c88e / 62.0a1 / 20180623220115 / files
nightly win32
5dc06b87c88e / 62.0a1 / 20180623220115 / files
nightly win64
5dc06b87c88e / 62.0a1 / 20180623220115 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -24,16 +24,17 @@
 #include "mozilla/ipc/Shmem.h"
 #include "mozilla/ipc/Transport.h"
 #include "mozilla/ipc/MessageLink.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/NotNull.h"
+#include "mozilla/Scoped.h"
 #include "mozilla/UniquePtr.h"
 #include "MainThreadUtils.h"
 #include "nsILabelableRunnable.h"
 
 #if defined(ANDROID) && defined(DEBUG)
 #include <android/log.h>
 #endif
 
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -7,17 +7,16 @@
 #ifndef js_Utility_h
 #define js_Utility_h
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Compiler.h"
 #include "mozilla/Move.h"
-#include "mozilla/Scoped.h"
 #include "mozilla/TemplateLib.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WrappingOperations.h"
 
 #include <stdlib.h>
 #include <string.h>
 
 #ifdef JS_OOM_DO_BACKTRACES
@@ -601,43 +600,16 @@ js_pod_realloc(T* prior, size_t oldSize,
 {
     MOZ_ASSERT(!(oldSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value));
     size_t bytes;
     if (MOZ_UNLIKELY(!js::CalculateAllocSize<T>(newSize, &bytes)))
         return nullptr;
     return static_cast<T*>(js_realloc(prior, bytes));
 }
 
-namespace js {
-
-template<typename T>
-struct ScopedFreePtrTraits
-{
-    typedef T* type;
-    static T* empty() { return nullptr; }
-    static void release(T* ptr) { js_free(ptr); }
-};
-SCOPED_TEMPLATE(ScopedJSFreePtr, ScopedFreePtrTraits)
-
-template <typename T>
-struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
-{
-    static void release(T* ptr) { js_delete(ptr); }
-};
-SCOPED_TEMPLATE(ScopedJSDeletePtr, ScopedDeletePtrTraits)
-
-template <typename T>
-struct ScopedReleasePtrTraits : public ScopedFreePtrTraits<T>
-{
-    static void release(T* ptr) { if (ptr) ptr->release(); }
-};
-SCOPED_TEMPLATE(ScopedReleasePtr, ScopedReleasePtrTraits)
-
-} /* namespace js */
-
 namespace JS {
 
 template<typename T>
 struct DeletePolicy
 {
     constexpr DeletePolicy() {}
 
     template<typename U>
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -3346,17 +3346,17 @@ reflect_parse(JSContext* cx, uint32_t ar
                                   "Reflect.parse", "0", "s");
         return false;
     }
 
     RootedString src(cx, ToString<CanGC>(cx, args[0]));
     if (!src)
         return false;
 
-    ScopedJSFreePtr<char> filename;
+    UniqueChars filename;
     uint32_t lineno = 1;
     bool loc = true;
     RootedObject builder(cx);
     ParseGoal target = ParseGoal::Script;
 
     RootedValue arg(cx, args.get(1));
 
     if (!arg.isNullOrUndefined()) {
@@ -3385,17 +3385,17 @@ reflect_parse(JSContext* cx, uint32_t ar
             if (!GetPropertyDefault(cx, config, sourceId, nullVal, &prop))
                 return false;
 
             if (!prop.isNullOrUndefined()) {
                 RootedString str(cx, ToString<CanGC>(cx, prop));
                 if (!str)
                     return false;
 
-                filename = JS_EncodeString(cx, str);
+                filename.reset(JS_EncodeString(cx, str));
                 if (!filename)
                     return false;
             }
 
             /* config.line */
             RootedId lineId(cx, NameToId(cx->names().line));
             RootedValue oneValue(cx, Int32Value(1));
             if (!GetPropertyDefault(cx, config, lineId, oneValue, &prop) ||
@@ -3446,30 +3446,30 @@ reflect_parse(JSContext* cx, uint32_t ar
             target = ParseGoal::Module;
         } else {
             JS_ReportErrorASCII(cx, "Bad target value, expected 'script' or 'module'");
             return false;
         }
     }
 
     /* Extract the builder methods first to report errors before parsing. */
-    ASTSerializer serialize(cx, loc, filename, lineno);
+    ASTSerializer serialize(cx, loc, filename.get(), lineno);
     if (!serialize.init(builder))
         return false;
 
     JSLinearString* linear = src->ensureLinear(cx);
     if (!linear)
         return false;
 
     AutoStableStringChars linearChars(cx);
     if (!linearChars.initTwoByte(cx, linear))
         return false;
 
     CompileOptions options(cx);
-    options.setFileAndLine(filename, lineno);
+    options.setFileAndLine(filename.get(), lineno);
     options.setCanLazilyParse(false);
     options.allowHTMLComments = target == ParseGoal::Script;
     mozilla::Range<const char16_t> chars = linearChars.twoByteRange();
     UsedNameTracker usedNames(cx);
     if (!usedNames.init())
         return false;
 
     RootedScriptSourceObject sourceObject(cx, frontend::CreateScriptSourceObject(cx, options,
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -34,16 +34,17 @@
 #include "jsnum.h"
 
 #include "builtin/TypedObject.h"
 #include "ctypes/Library.h"
 #include "gc/FreeOp.h"
 #include "gc/Policy.h"
 #include "gc/Zone.h"
 #include "jit/AtomicOperations.h"
+#include "js/UniquePtr.h"
 #include "js/Vector.h"
 #include "util/Windows.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 
 #include "vm/JSObject-inl.h"
 
 using namespace std;
@@ -8388,35 +8389,34 @@ CDataFinalizer::Construct(JSContext* cx,
   size_t sizeArg;
   RootedValue valData(cx, args[0]);
   if (!CType::GetSafeSize(objArgType, &sizeArg)) {
     RootedValue valCodeType(cx, ObjectValue(*objCodeType));
     return TypeError(cx, "a function with one known size argument",
                      valCodeType);
   }
 
-  ScopedJSFreePtr<void> cargs(malloc(sizeArg));
+  UniquePtr<void, JS::FreePolicy> cargs(malloc(sizeArg));
 
   if (!ImplicitConvert(cx, valData, objArgType, cargs.get(),
                        ConversionType::Finalizer, &freePointer,
                        objCodePtrType, 0)) {
     return false;
   }
   if (freePointer) {
     // Note: We could handle that case, if necessary.
     JS_ReportErrorASCII(cx, "Internal Error during CDataFinalizer. Object cannot be represented");
     return false;
   }
 
   // 4. Prepare buffer for holding return value
 
-  ScopedJSFreePtr<void> rvalue;
+  UniquePtr<void, JS::FreePolicy> rvalue;
   if (CType::GetTypeCode(returnType) != TYPE_void_t) {
-    rvalue = malloc(Align(CType::GetSize(returnType),
-                          sizeof(ffi_arg)));
+    rvalue.reset(malloc(Align(CType::GetSize(returnType), sizeof(ffi_arg))));
   } //Otherwise, simply do not allocate
 
   // 5. Create |objResult|
 
   JSObject* objResult = JS_NewObjectWithGivenProto(cx, &sCDataFinalizerClass, objProto);
   if (!objResult) {
     return false;
   }
@@ -8460,28 +8460,28 @@ CDataFinalizer::Construct(JSContext* cx,
   ffi_type* rtype = CType::GetFFIType(cx, funInfoFinalizer->mReturnType);
   if (!rtype) {
     JS_ReportErrorASCII(cx, "Internal Error: "
                         "Could not access ffi type of CDataFinalizer");
     return false;
   }
 
   // 7. Store C information as private
-  ScopedJSFreePtr<CDataFinalizer::Private>
+  UniquePtr<CDataFinalizer::Private, JS::FreePolicy>
     p((CDataFinalizer::Private*)malloc(sizeof(CDataFinalizer::Private)));
 
   memmove(&p->CIF, &funInfoFinalizer->mCIF, sizeof(ffi_cif));
 
-  p->cargs = cargs.forget();
-  p->rvalue = rvalue.forget();
+  p->cargs = cargs.release();
+  p->rvalue = rvalue.release();
   p->cargs_size = sizeArg;
   p->code = code;
 
 
-  JS_SetPrivate(objResult, p.forget());
+  JS_SetPrivate(objResult, p.release());
   args.rval().setObject(*objResult);
   return true;
 }
 
 
 /*
  * Actually call the finalizer. Does not perform any cleanup on the object.
  *
--- a/js/src/ds/OrderedHashTable.h
+++ b/js/src/ds/OrderedHashTable.h
@@ -97,16 +97,19 @@ class OrderedHashTable
         }
     }
 
   public:
     OrderedHashTable(AllocPolicy& ap, mozilla::HashCodeScrambler hcs)
       : hashTable(nullptr),
         data(nullptr),
         dataLength(0),
+        dataCapacity(0),
+        liveCount(0),
+        hashShift(0),
         ranges(nullptr),
         nurseryRanges(nullptr),
         alloc(ap),
         hcs(hcs)
     {}
 
     MOZ_MUST_USE bool init() {
         MOZ_ASSERT(!hashTable, "init must be called at most once");
--- a/js/src/frontend/BinSource.h
+++ b/js/src/frontend/BinSource.h
@@ -103,16 +103,17 @@ class BinASTParser : public BinASTParser
     using AutoTuple = typename Tokenizer::AutoTuple;
     using BinFields = typename Tokenizer::BinFields;
     using Chars = typename Tokenizer::Chars;
 
   public:
     BinASTParser(JSContext* cx, LifoAlloc& alloc, UsedNameTracker& usedNames, const JS::ReadOnlyCompileOptions& options)
         : BinASTParserBase(cx, alloc, usedNames)
         , options_(options)
+        , variableDeclarationKind_(VariableDeclarationKind::Var)
     {
     }
     ~BinASTParser()
     {
     }
 
     /**
      * Parse a buffer, returning a node (which may be nullptr) in case of success
--- a/js/src/frontend/BinTokenReaderBase.h
+++ b/js/src/frontend/BinTokenReaderBase.h
@@ -70,16 +70,17 @@ class MOZ_STACK_CLASS BinTokenReaderBase
     MOZ_MUST_USE ErrorResult<JS::Error&> raiseInvalidNumberOfFields(
         const BinKind kind, const uint32_t expected, const uint32_t got);
     MOZ_MUST_USE ErrorResult<JS::Error&> raiseInvalidField(const char* kind,
         const BinField field);
 
   protected:
     BinTokenReaderBase(JSContext* cx, const uint8_t* start, const size_t length)
         : cx_(cx)
+        , poisoned_(false)
         , start_(start)
         , current_(start)
         , stop_(start + length)
         , latestKnownGoodPos_(0)
     { }
 
     /**
      * Read a single byte.
--- a/js/src/frontend/BinTokenReaderMultipart.cpp
+++ b/js/src/frontend/BinTokenReaderMultipart.cpp
@@ -339,17 +339,18 @@ BinTokenReaderMultipart::enterList(uint3
 
 void
 BinTokenReaderMultipart::AutoBase::init()
 {
     initialized_ = true;
 }
 
 BinTokenReaderMultipart::AutoBase::AutoBase(BinTokenReaderMultipart& reader)
-    : reader_(reader)
+    : initialized_(false)
+    , reader_(reader)
 { }
 
 BinTokenReaderMultipart::AutoBase::~AutoBase()
 {
     // By now, the `AutoBase` must have been deinitialized by calling `done()`.
     // The only case in which we can accept not calling `done()` is if we have
     // bailed out because of an error.
     MOZ_ASSERT_IF(initialized_, reader_.cx_->isExceptionPending());
--- a/js/src/frontend/BinTokenReaderTester.cpp
+++ b/js/src/frontend/BinTokenReaderTester.cpp
@@ -350,17 +350,18 @@ BinTokenReaderTester::enterList(uint32_t
 
 void
 BinTokenReaderTester::AutoBase::init()
 {
     initialized_ = true;
 }
 
 BinTokenReaderTester::AutoBase::AutoBase(BinTokenReaderTester& reader)
-    : reader_(reader)
+    : initialized_(false)
+    , reader_(reader)
 { }
 
 BinTokenReaderTester::AutoBase::~AutoBase()
 {
     // By now, the `AutoBase` must have been deinitialized by calling `done()`.
     // The only case in which we can accept not calling `done()` is if we have
     // bailed out because of an error.
     MOZ_ASSERT_IF(initialized_, reader_.cx_->isExceptionPending());
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1691,17 +1691,18 @@ class MOZ_STACK_CLASS TryEmitter
 
   public:
     TryEmitter(BytecodeEmitter* bce, Kind kind, ControlKind controlKind)
       : bce_(bce),
         kind_(kind),
         controlKind_(controlKind),
         depth_(0),
         noteIndex_(0),
-        tryStart_(0)
+        tryStart_(0),
+        tryEnd_{}
 #ifdef DEBUG
       , state_(State::Start)
 #endif
     {
         if (controlKind_ == ControlKind::Syntactic)
             controlInfo_.emplace(bce_, hasFinally() ? StatementKind::Finally : StatementKind::Try);
         finallyStart_.offset = 0;
     }
@@ -2506,16 +2507,17 @@ BytecodeEmitter::BytecodeEmitter(Bytecod
   : sc(sc),
     cx(sc->context),
     parent(parent),
     script(cx, script),
     lazyScript(cx, lazyScript),
     prologue(cx, lineNum),
     main(cx, lineNum),
     current(&main),
+    parser(nullptr),
     atomIndices(cx->frontendCollectionPool()),
     firstLine(lineNum),
     maxFixedSlots(0),
     maxStackDepth(0),
     stackDepth(0),
     emitLevel(0),
     bodyScopeIndex(UINT32_MAX),
     varEmitterScope(nullptr),
--- a/js/src/frontend/NameCollections.h
+++ b/js/src/frontend/NameCollections.h
@@ -108,17 +108,19 @@ struct RecyclableAtomMapValueWrapper
         uint64_t dummy;
     };
 
     static void assertInvariant() {
         static_assert(sizeof(Wrapped) <= sizeof(uint64_t),
                       "Can only recycle atom maps with values smaller than uint64");
     }
 
-    RecyclableAtomMapValueWrapper() {
+    RecyclableAtomMapValueWrapper()
+      : dummy(0)
+    {
         assertInvariant();
     }
 
     MOZ_IMPLICIT RecyclableAtomMapValueWrapper(Wrapped w)
       : wrapped(w)
     {
         assertInvariant();
     }
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -191,17 +191,20 @@ struct KeywordInfo;
 
 namespace js {
 namespace frontend {
 
 struct TokenPos {
     uint32_t    begin;  // Offset of the token's first char.
     uint32_t    end;    // Offset of 1 past the token's last char.
 
-    TokenPos() {}
+    TokenPos()
+      : begin(0),
+        end(0)
+    {}
     TokenPos(uint32_t begin, uint32_t end) : begin(begin), end(end) {}
 
     // Return a TokenPos that covers left, right, and anything in between.
     static TokenPos box(const TokenPos& left, const TokenPos& right) {
         MOZ_ASSERT(left.begin <= left.end);
         MOZ_ASSERT(left.end <= right.begin);
         MOZ_ASSERT(right.begin <= right.end);
         return TokenPos(left.begin, right.end);
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -428,26 +428,22 @@ class Nursery
         mozilla::EnumeratedArray<ProfileKey, ProfileKey::KeyCount, mozilla::TimeStamp>;
     using ProfileDurations =
         mozilla::EnumeratedArray<ProfileKey, ProfileKey::KeyCount, mozilla::TimeDuration>;
 
     ProfileTimes startTimes_;
     ProfileDurations profileDurations_;
     ProfileDurations totalDurations_;
 
-    /*
-     * This data is initialised only if the nursery is enabled and after at
-     * least one call to Nursery::collect()
-     */
     struct {
-        JS::gcreason::Reason reason;
-        size_t nurseryCapacity;
-        size_t nurseryLazyCapacity;
-        size_t nurseryUsedBytes;
-        size_t tenuredBytes;
+        JS::gcreason::Reason reason = JS::gcreason::NO_REASON;
+        size_t nurseryCapacity = 0;
+        size_t nurseryLazyCapacity = 0;
+        size_t nurseryUsedBytes = 0;
+        size_t tenuredBytes = 0;
     } previousGC;
 
     /*
      * Calculate the promotion rate of the most recent minor GC.
      * The valid_for_tenuring parameter is used to return whether this
      * promotion rate is accurate enough (the nursery was full enough) to be
      * used for tenuring and other decisions.
      *
--- a/js/src/gc/Rooting.h
+++ b/js/src/gc/Rooting.h
@@ -129,17 +129,19 @@ class FakeMutableHandle : public js::Mut
         *ptr = v;
     }
 
     DECLARE_POINTER_CONSTREF_OPS(T);
     DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr);
     DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(*ptr);
 
   private:
-    FakeMutableHandle() {}
+    FakeMutableHandle()
+      : ptr(nullptr)
+    {}
     DELETE_ASSIGNMENT_OPS(FakeMutableHandle, T);
 
     T* ptr;
 };
 
 template <typename T> class MaybeRooted<T, NoGC>
 {
   public:
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -739,16 +739,19 @@ Statistics::Statistics(JSRuntime* rt)
   : runtime(rt),
     gcTimerFile(nullptr),
     gcDebugFile(nullptr),
     nonincrementalReason_(gc::AbortReason::None),
     preBytes(0),
     thresholdTriggered(false),
     triggerAmount(0.0),
     triggerThreshold(0.0),
+    startingMinorGCNumber(0),
+    startingMajorGCNumber(0),
+    startingSliceNumber(0),
     maxPauseInInterval(0),
     sliceCallback(nullptr),
     nurseryCollectionCallback(nullptr),
     aborted(false),
     enableProfiling_(false),
     sliceCount_(0)
 {
     for (auto& count : counts)
--- a/js/src/gc/Statistics.h
+++ b/js/src/gc/Statistics.h
@@ -216,17 +216,18 @@ struct Statistics
     struct SliceData {
         SliceData(SliceBudget budget, JS::gcreason::Reason reason,
                   TimeStamp start, size_t startFaults, gc::State initialState)
           : budget(budget), reason(reason),
             initialState(initialState),
             finalState(gc::State::NotActive),
             resetReason(gc::AbortReason::None),
             start(start),
-            startFaults(startFaults)
+            startFaults(startFaults),
+            endFaults(0)
         {}
 
         SliceBudget budget;
         JS::gcreason::Reason reason;
         gc::State initialState, finalState;
         gc::AbortReason resetReason;
         TimeStamp start, end;
         size_t startFaults, endFaults;
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -1647,16 +1647,17 @@ IsLatin1Equivalent(char16_t c, RegExpCom
 }
 
 // Attempts to compile the regexp using an Irregexp code generator.  Returns
 // a fixed array or a null handle depending on whether it succeeded.
 RegExpCompiler::RegExpCompiler(JSContext* cx, LifoAlloc* alloc, int capture_count,
                                bool ignore_case, bool latin1, bool match_only, bool unicode)
   : next_register_(2 * (capture_count + 1)),
     recursion_depth_(0),
+    macro_assembler_(nullptr),
     ignore_case_(ignore_case),
     latin1_(latin1),
     match_only_(match_only),
     unicode_(unicode),
     reg_exp_too_big_(false),
     current_expansion_factor_(1),
     frequency_collator_(),
     cx_(cx),
--- a/js/src/irregexp/RegExpEngine.h
+++ b/js/src/irregexp/RegExpEngine.h
@@ -681,16 +681,17 @@ class ActionNode : public SeqRegExpNode
         BEGIN_SUBMATCH,
         POSITIVE_SUBMATCH_SUCCESS,
         EMPTY_MATCH_CHECK,
         CLEAR_CAPTURES
     };
 
     ActionNode(ActionType action_type, RegExpNode* on_success)
       : SeqRegExpNode(on_success),
+        data_{},
         action_type_(action_type)
     {}
 
     static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success);
     static ActionNode* IncrementRegister(int reg, RegExpNode* on_success);
     static ActionNode* StorePosition(int reg,
                                      bool is_capture,
                                      RegExpNode* on_success);
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/Ion.h"
 
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/ThreadLocal.h"
+#include "mozilla/Unused.h"
 
 #include "gc/FreeOp.h"
 #include "gc/Marking.h"
 #include "jit/AliasAnalysis.h"
 #include "jit/AlignmentMaskAnalysis.h"
 #include "jit/BacktrackingAllocator.h"
 #include "jit/BaselineFrame.h"
 #include "jit/BaselineInspector.h"
@@ -41,16 +42,17 @@
 #include "jit/PerfSpewer.h"
 #include "jit/RangeAnalysis.h"
 #include "jit/ScalarReplacement.h"
 #include "jit/Sink.h"
 #include "jit/StupidAllocator.h"
 #include "jit/ValueNumbering.h"
 #include "jit/WasmBCE.h"
 #include "js/Printf.h"
+#include "js/UniquePtr.h"
 #include "util/Windows.h"
 #include "vm/Debugger.h"
 #include "vm/HelperThreads.h"
 #include "vm/Realm.h"
 #include "vm/TraceLogging.h"
 #include "vtune/VTuneWrapper.h"
 
 #include "gc/PrivateIterators-inl.h"
@@ -2040,23 +2042,21 @@ IonCompile(JSContext* cx, JSScript* scri
     AutoTraceLog logCompile(logger, TraceLogger_IonCompilation);
 
     // Make sure the script's canonical function isn't lazy. We can't de-lazify
     // it in a helper thread.
     script->ensureNonLazyCanonicalFunction();
 
     TrackPropertiesForSingletonScopes(cx, script, baselineFrame);
 
-    LifoAlloc* alloc = cx->new_<LifoAlloc>(TempAllocator::PreferredLifoChunkSize);
+    auto alloc = cx->make_unique<LifoAlloc>(TempAllocator::PreferredLifoChunkSize);
     if (!alloc)
         return AbortReason::Alloc;
 
-    ScopedJSDeletePtr<LifoAlloc> autoDelete(alloc);
-
-    TempAllocator* temp = alloc->new_<TempAllocator>(alloc);
+    TempAllocator* temp = alloc->new_<TempAllocator>(alloc.get());
     if (!temp)
         return AbortReason::Alloc;
 
     JitContext jctx(cx, temp);
 
     if (!cx->realm()->ensureJitRealmExists(cx))
         return AbortReason::Alloc;
 
@@ -2179,34 +2179,33 @@ IonCompile(JSContext* cx, JSScript* scri
             return AbortReason::Alloc;
         }
 
         if (!recompile)
             builderScript->setIonScript(cx->runtime(), ION_COMPILING_SCRIPT);
 
         // The allocator and associated data will be destroyed after being
         // processed in the finishedOffThreadCompilations list.
-        autoDelete.forget();
+        mozilla::Unused << alloc.release();
 
         return AbortReason::NoAbort;
     }
 
     bool succeeded = false;
     {
-        ScopedJSDeletePtr<CodeGenerator> codegen;
         AutoEnterAnalysis enter(cx);
-        codegen = CompileBackEnd(builder);
+        UniquePtr<CodeGenerator> codegen(CompileBackEnd(builder));
         if (!codegen) {
             JitSpew(JitSpew_IonAbort, "Failed during back-end compilation.");
             if (cx->isExceptionPending())
                 return AbortReason::Error;
             return AbortReason::Disable;
         }
 
-        succeeded = LinkCodeGen(cx, builder, codegen);
+        succeeded = LinkCodeGen(cx, builder, codegen.get());
     }
 
     if (succeeded)
         return AbortReason::NoAbort;
     if (cx->isExceptionPending())
         return AbortReason::Error;
     return AbortReason::Disable;
 }
--- a/js/src/jsapi-tests/testPrivateGCThingValue.cpp
+++ b/js/src/jsapi-tests/testPrivateGCThingValue.cpp
@@ -19,16 +19,18 @@ class TestTracer : public JS::CallbackTr
 
   public:
     js::gc::Cell* expectedCell;
     JS::TraceKind expectedKind;
     bool found;
 
     explicit TestTracer(JSContext* cx)
       : JS::CallbackTracer(cx),
+        expectedCell(nullptr),
+        expectedKind(static_cast<JS::TraceKind>(0)),
         found(false)
     { }
 };
 
 static const JSClass TestClass = {
     "TestClass",
     JSCLASS_HAS_RESERVED_SLOTS(1)
 };
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -474,17 +474,21 @@ class ExternalData {
  */
 class AutoLeaveZeal
 {
     JSContext* cx_;
     uint32_t zealBits_;
     uint32_t frequency_;
 
   public:
-    explicit AutoLeaveZeal(JSContext* cx) : cx_(cx) {
+    explicit AutoLeaveZeal(JSContext* cx)
+      : cx_(cx),
+        zealBits_(0),
+        frequency_(0)
+    {
         uint32_t dummy;
         JS_GetGCZealBits(cx_, &zealBits_, &frequency_, &dummy);
         JS_SetGCZeal(cx_, 0, 0);
         JS::PrepareForFullGC(cx_);
         JS::NonIncrementalGC(cx_, GC_SHRINK, JS::gcreason::DEBUG_GC);
     }
     ~AutoLeaveZeal() {
         JS_SetGCZeal(cx_, 0, 0);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6625,17 +6625,17 @@ JS_ObjectIsDate(JSContext* cx, HandleObj
  * Regular Expressions.
  */
 JS_PUBLIC_API(JSObject*)
 JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned flags)
 {
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
-    ScopedJSFreePtr<char16_t> chars(InflateString(cx, bytes, length));
+    UniqueTwoByteChars chars(InflateString(cx, bytes, length));
     if (!chars)
         return nullptr;
 
     return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags), cx->tempLifoAlloc(),
                                 GenericObject);
 }
 
 JS_PUBLIC_API(JSObject*)
@@ -6864,17 +6864,20 @@ JS::AutoSaveExceptionState::~AutoSaveExc
             context->overRecursed_ = wasOverRecursed;
             context->throwing = true;
             context->unwrappedException() = exceptionValue;
         }
     }
 }
 
 struct JSExceptionState {
-    explicit JSExceptionState(JSContext* cx) : exception(cx) {}
+    explicit JSExceptionState(JSContext* cx)
+      : throwing(false),
+        exception(cx)
+    {}
     bool throwing;
     PersistentRootedValue exception;
 };
 
 JS_PUBLIC_API(JSExceptionState*)
 JS_SaveExceptionState(JSContext* cx)
 {
     JSExceptionState* state;
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1419,17 +1419,17 @@ class MOZ_STACK_CLASS JS_FRIEND_API(Auto
      * When copying string char, use this many bytes of inline storage.  This is
      * chosen to allow the inline string types to be copied without allocating.
      * This is asserted in AutoStableStringChars::allocOwnChars.
      */
     static const size_t InlineCapacity = 24;
 
     /* Ensure the string is kept alive while we're using its chars. */
     JS::RootedString s_;
-    union {
+    MOZ_INIT_OUTSIDE_CTOR union {
         const char16_t* twoByteChars_;
         const JS::Latin1Char* latin1Chars_;
     };
     mozilla::Maybe<Vector<uint8_t, InlineCapacity>> ownChars_;
     enum State { Uninitialized, Latin1, TwoByte };
     State state_;
 
   public:
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -81,32 +81,32 @@ EnsureDtoaState(JSContext* cx)
  * Call js_strtod_harder to get the correct answer.
  */
 template <typename CharT>
 static bool
 ComputeAccurateDecimalInteger(JSContext* cx, const CharT* start, const CharT* end,
                               double* dp)
 {
     size_t length = end - start;
-    ScopedJSFreePtr<char> cstr(cx->pod_malloc<char>(length + 1));
+    UniqueChars cstr(cx->pod_malloc<char>(length + 1));
     if (!cstr)
         return false;
 
     for (size_t i = 0; i < length; i++) {
         char c = char(start[i]);
         MOZ_ASSERT(IsAsciiAlphanumeric(c));
         cstr[i] = c;
     }
     cstr[length] = 0;
 
     if (!EnsureDtoaState(cx))
         return false;
 
     char* estr;
-    *dp = js_strtod_harder(cx->dtoaState, cstr, &estr);
+    *dp = js_strtod_harder(cx->dtoaState, cstr.get(), &estr);
 
     return true;
 }
 
 namespace {
 
 template <typename CharT>
 class BinaryDigitReader
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -879,33 +879,33 @@ RunBinAST(JSContext* cx, const char* fil
 static bool
 InitModuleLoader(JSContext* cx)
 {
 
     // Decompress and evaluate the embedded module loader source to initialize
     // the module loader for the current compartment.
 
     uint32_t srcLen = moduleloader::GetRawScriptsSize();
-    ScopedJSFreePtr<char> src(cx->pod_malloc<char>(srcLen));
+    UniqueChars src(cx->pod_malloc<char>(srcLen));
     if (!src || !DecompressString(moduleloader::compressedSources, moduleloader::GetCompressedSize(),
                                   reinterpret_cast<unsigned char*>(src.get()), srcLen))
     {
         return false;
     }
 
     CompileOptions options(cx);
     options.setIntroductionType("shell module loader");
     options.setFileAndLine("shell/ModuleLoader.js", 1);
     options.setSelfHostingMode(false);
     options.setCanLazilyParse(false);
     options.werrorOption = true;
     options.strictOption = true;
 
     RootedValue rv(cx);
-    return Evaluate(cx, options, src, srcLen, &rv);
+    return Evaluate(cx, options, src.get(), srcLen, &rv);
 }
 
 static bool
 GetLoaderObject(JSContext* cx, MutableHandleObject resultOut)
 {
     // Look up the |Reflect.Loader| object that has been defined by the module
     // loader.
 
--- a/js/src/util/StringBuffer.cpp
+++ b/js/src/util/StringBuffer.cpp
@@ -2,16 +2,17 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "util/StringBuffer.h"
 
 #include "mozilla/Range.h"
+#include "mozilla/Unused.h"
 
 #include "vm/JSObject-inl.h"
 #include "vm/StringType-inl.h"
 
 using namespace js;
 
 template <typename CharT, class Buffer>
 static CharT*
@@ -74,31 +75,31 @@ StringBuffer::inflateChars()
 template <typename CharT, class Buffer>
 static JSFlatString*
 FinishStringFlat(JSContext* cx, StringBuffer& sb, Buffer& cb)
 {
     size_t len = sb.length();
     if (!sb.append('\0'))
         return nullptr;
 
-    ScopedJSFreePtr<CharT> buf(ExtractWellSized<CharT>(cx, cb));
+    UniquePtr<CharT[], JS::FreePolicy> buf(ExtractWellSized<CharT>(cx, cb));
     if (!buf)
         return nullptr;
 
     JSFlatString* str = NewStringDontDeflate<CanGC>(cx, buf.get(), len);
     if (!str)
         return nullptr;
 
     /*
      * The allocation was made on a TempAllocPolicy, so account for the string
      * data on the string's zone.
      */
     cx->updateMallocCounter(sizeof(CharT) * len);
 
-    buf.forget();
+    mozilla::Unused << buf.release();
     return str;
 }
 
 JSFlatString*
 StringBuffer::finishString()
 {
     size_t len = length();
     if (len == 0)
--- a/js/src/vm/BytecodeUtil.h
+++ b/js/src/vm/BytecodeUtil.h
@@ -468,17 +468,17 @@ class SrcNoteLineScanner
      * Is the current op the first one after a line change directive? Note that
      * multiple ops may be "first" if a line directive is used to return to a
      * previous line (eg, with a for loop increment expression.)
      */
     bool lineHeader;
 
   public:
     SrcNoteLineScanner(jssrcnote* sn, uint32_t lineno)
-        : offset(0), sn(sn), lineno(lineno)
+        : offset(0), sn(sn), lineno(lineno), lineHeader(false)
     {
     }
 
     /*
      * This is called repeatedly with always-advancing relpc values. The src
      * notes are tuples of <PC offset from prev src note, type, args>. Scan
      * through, updating the lineno, until the next src note is for a later
      * bytecode.
--- a/js/src/vm/Caches.h
+++ b/js/src/vm/Caches.h
@@ -78,17 +78,17 @@ struct EvalCacheEntry
     }
 };
 
 struct EvalCacheLookup
 {
     explicit EvalCacheLookup(JSContext* cx) : str(cx), callerScript(cx) {}
     RootedLinearString str;
     RootedScript callerScript;
-    jsbytecode* pc;
+    MOZ_INIT_OUTSIDE_CTOR jsbytecode* pc;
 };
 
 struct EvalCacheHashPolicy
 {
     typedef EvalCacheLookup Lookup;
 
     static HashNumber hash(const Lookup& l);
     static bool match(const EvalCacheEntry& entry, const EvalCacheLookup& l);
--- a/js/src/vm/Compartment.cpp
+++ b/js/src/vm/Compartment.cpp
@@ -122,32 +122,32 @@ CopyStringPure(JSContext* cx, JSString* 
             return nullptr;
 
         return chars.isLatin1()
                ? NewStringCopyN<CanGC>(cx, chars.latin1Range().begin().get(), len)
                : NewStringCopyNDontDeflate<CanGC>(cx, chars.twoByteRange().begin().get(), len);
     }
 
     if (str->hasLatin1Chars()) {
-        ScopedJSFreePtr<Latin1Char> copiedChars;
-        if (!str->asRope().copyLatin1CharsZ(cx, copiedChars))
+        UniquePtr<Latin1Char[], JS::FreePolicy> copiedChars = str->asRope().copyLatin1CharsZ(cx);
+        if (!copiedChars)
             return nullptr;
 
-        auto* rawCopiedChars = copiedChars.forget();
+        auto* rawCopiedChars = copiedChars.release();
         auto* result = NewString<CanGC>(cx, rawCopiedChars, len);
         if (!result)
             js_free(rawCopiedChars);
         return result;
     }
 
-    ScopedJSFreePtr<char16_t> copiedChars;
-    if (!str->asRope().copyTwoByteCharsZ(cx, copiedChars))
+    UniqueTwoByteChars copiedChars = str->asRope().copyTwoByteCharsZ(cx);
+    if (!copiedChars)
         return nullptr;
 
-    auto* rawCopiedChars = copiedChars.forget();
+    auto* rawCopiedChars = copiedChars.release();
     auto* result = NewStringDontDeflate<CanGC>(cx, rawCopiedChars, len);
     if (!result)
         js_free(rawCopiedChars);
     return result;
 }
 
 bool
 Compartment::wrap(JSContext* cx, MutableHandleString strp)
--- a/js/src/vm/Compression.cpp
+++ b/js/src/vm/Compression.cpp
@@ -40,16 +40,23 @@ Compressor::Compressor(const unsigned ch
     MOZ_ASSERT(inplen > 0);
     zs.opaque = nullptr;
     zs.next_in = (Bytef*)inp;
     zs.avail_in = 0;
     zs.next_out = nullptr;
     zs.avail_out = 0;
     zs.zalloc = zlib_alloc;
     zs.zfree = zlib_free;
+    zs.total_in = 0;
+    zs.total_out = 0;
+    zs.msg = nullptr;
+    zs.state = nullptr;
+    zs.data_type = 0;
+    zs.adler = 0;
+    zs.reserved = 0;
 
     // Reserve space for the CompressedDataHeader.
     outbytes = sizeof(CompressedDataHeader);
 }
 
 Compressor::~Compressor()
 {
     if (initialized) {
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4225,19 +4225,23 @@ class MOZ_STACK_CLASS Debugger::ScriptQu
         cx(cx),
         debugger(dbg),
         iterMarker(&cx->runtime()->gc),
         realms(cx->zone()),
         url(cx),
         displayURLString(cx),
         hasSource(false),
         source(cx, AsVariant(static_cast<ScriptSourceObject*>(nullptr))),
+        hasLine(false),
+        line(0),
+        innermost(false),
         innermostForRealm(cx->zone()),
         vector(cx, ScriptVector(cx)),
-        wasmInstanceVector(cx, WasmInstanceObjectVector(cx))
+        wasmInstanceVector(cx, WasmInstanceObjectVector(cx)),
+        oom(false)
     {}
 
     /*
      * Initialize this ScriptQuery. Raise an error and return false if we
      * haven't enough memory.
      */
     bool init() {
         if (!realms.init() ||
@@ -5458,17 +5462,20 @@ DebuggerScript_getStartLine(JSContext* c
     return true;
 }
 
 struct DebuggerScriptGetLineCountMatcher
 {
     JSContext* cx_;
     double totalLines;
 
-    explicit DebuggerScriptGetLineCountMatcher(JSContext* cx) : cx_(cx) {}
+    explicit DebuggerScriptGetLineCountMatcher(JSContext* cx)
+      : cx_(cx),
+        totalLines(0.0)
+    {}
     using ReturnType = bool;
 
     ReturnType match(HandleScript script) {
         totalLines = double(GetScriptLineExtent(script));
         return true;
     }
     ReturnType match(Handle<WasmInstanceObject*> wasmInstance) {
         uint32_t result;
@@ -6682,17 +6689,21 @@ DebuggerScript_clearAllBreakpoints(JSCon
 
 class DebuggerScriptIsInCatchScopeMatcher
 {
     JSContext* cx_;
     size_t offset_;
     bool isInCatch_;
 
   public:
-    explicit DebuggerScriptIsInCatchScopeMatcher(JSContext* cx, size_t offset) : cx_(cx), offset_(offset) { }
+    explicit DebuggerScriptIsInCatchScopeMatcher(JSContext* cx, size_t offset)
+      : cx_(cx),
+        offset_(offset),
+        isInCatch_(false)
+    { }
     using ReturnType = bool;
 
     inline bool isInCatch() const { return isInCatch_; }
 
     ReturnType match(HandleScript script) {
         if (!EnsureScriptOffsetIsValid(cx_, script, offset_))
             return false;
 
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/Maybe.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Unused.h"
 
 #include "builtin/Promise.h"
 #include "frontend/BytecodeCompiler.h"
 #include "gc/GCInternals.h"
 #include "jit/IonBuilder.h"
+#include "js/UniquePtr.h"
 #include "js/Utility.h"
 #include "threading/CpuCount.h"
 #include "util/NativeStack.h"
 #include "vm/Debugger.h"
 #include "vm/ErrorReporting.h"
 #include "vm/SharedImmutableStringsCache.h"
 #include "vm/Time.h"
 #include "vm/TraceLogging.h"
@@ -821,80 +822,75 @@ StartOffThreadParseTask(JSContext* cx, P
     return true;
 }
 
 bool
 js::StartOffThreadParseScript(JSContext* cx, const ReadOnlyCompileOptions& options,
                               const char16_t* chars, size_t length,
                               JS::OffThreadCompileCallback callback, void* callbackData)
 {
-    ScopedJSDeletePtr<ParseTask> task;
-    task = cx->new_<ScriptParseTask>(cx, chars, length, callback, callbackData);
-    if (!task || !StartOffThreadParseTask(cx, task, options))
+    auto task = cx->make_unique<ScriptParseTask>(cx, chars, length, callback, callbackData);
+    if (!task || !StartOffThreadParseTask(cx, task.get(), options))
         return false;
 
-    task.forget();
+    Unused << task.release();
     return true;
 }
 
 bool
 js::StartOffThreadParseModule(JSContext* cx, const ReadOnlyCompileOptions& options,
                               const char16_t* chars, size_t length,
                               JS::OffThreadCompileCallback callback, void* callbackData)
 {
-    ScopedJSDeletePtr<ParseTask> task;
-    task = cx->new_<ModuleParseTask>(cx, chars, length, callback, callbackData);
-    if (!task || !StartOffThreadParseTask(cx, task, options))
+    auto task = cx->make_unique<ModuleParseTask>(cx, chars, length, callback, callbackData);
+    if (!task || !StartOffThreadParseTask(cx, task.get(), options))
         return false;
 
-    task.forget();
+    Unused << task.release();
     return true;
 }
 
 bool
 js::StartOffThreadDecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options,
                                const JS::TranscodeRange& range,
                                JS::OffThreadCompileCallback callback, void* callbackData)
 {
-    ScopedJSDeletePtr<ParseTask> task;
-    task = cx->new_<ScriptDecodeTask>(cx, range, callback, callbackData);
-    if (!task || !StartOffThreadParseTask(cx, task, options))
+    auto task = cx->make_unique<ScriptDecodeTask>(cx, range, callback, callbackData);
+    if (!task || !StartOffThreadParseTask(cx, task.get(), options))
         return false;
 
-    task.forget();
+    Unused << task.release();
     return true;
 }
 
 bool
 js::StartOffThreadDecodeMultiScripts(JSContext* cx, const ReadOnlyCompileOptions& options,
                                      JS::TranscodeSources& sources,
                                      JS::OffThreadCompileCallback callback, void* callbackData)
 {
-    ScopedJSDeletePtr<ParseTask> task;
-    task = cx->new_<MultiScriptsDecodeTask>(cx, sources, callback, callbackData);
-    if (!task || !StartOffThreadParseTask(cx, task, options))
+    auto task = cx->make_unique<MultiScriptsDecodeTask>(cx, sources, callback, callbackData);
+    if (!task || !StartOffThreadParseTask(cx, task.get(), options))
         return false;
 
-    task.forget();
+    Unused << task.release();
     return true;
 }
 
 #if defined(JS_BUILD_BINAST)
 
 bool
 js::StartOffThreadDecodeBinAST(JSContext* cx, const ReadOnlyCompileOptions& options,
                                const uint8_t* buf, size_t length,
                                JS::OffThreadCompileCallback callback, void *callbackData)
 {
-    ScopedJSDeletePtr<ParseTask> task;
-    task = cx->new_<BinASTDecodeTask>(cx, buf, length, callback, callbackData);
-    if (!task || !StartOffThreadParseTask(cx, task, options))
+    auto task = cx->make_unique<BinASTDecodeTask>(cx, buf, length, callback, callbackData);
+    if (!task || !StartOffThreadParseTask(cx, task.get(), options))
         return false;
 
-    task.forget();
+    Unused << task.release();
     return true;
 }
 
 #endif /* JS_BUILD_BINAST */
 
 void
 js::EnqueuePendingParseTasksAfterGC(JSRuntime* rt)
 {
@@ -1660,43 +1656,42 @@ GlobalHelperThreadState::removeFinishedP
 
 template <typename F, typename>
 bool
 GlobalHelperThreadState::finishParseTask(JSContext* cx, ParseTaskKind kind,
                                          JS::OffThreadToken* token, F&& finishCallback)
 {
     MOZ_ASSERT(cx->realm());
 
-    ScopedJSDeletePtr<ParseTask> parseTask(removeFinishedParseTask(kind, token));
+    Rooted<UniquePtr<ParseTask>> parseTask(cx, removeFinishedParseTask(kind, token));
 
     // Make sure we have all the constructors we need for the prototype
     // remapping below, since we can't GC while that's happening.
     if (!EnsureParserCreatedClasses(cx, kind)) {
-        LeaveParseTaskZone(cx->runtime(), parseTask);
+        LeaveParseTaskZone(cx->runtime(), parseTask.get().get());
         return false;
     }
 
-    mergeParseTaskRealm(cx, parseTask, cx->realm());
-
-    bool ok = finishCallback(parseTask);
+    mergeParseTaskRealm(cx, parseTask.get().get(), cx->realm());
+
+    bool ok = finishCallback(parseTask.get().get());
 
     for (auto& script : parseTask->scripts)
         releaseAssertSameCompartment(cx, script);
 
     if (!parseTask->finish(cx) || !ok)
         return false;
 
     // Report out of memory errors eagerly, or errors could be malformed.
     if (parseTask->outOfMemory) {
         ReportOutOfMemory(cx);
         return false;
     }
 
-    // Report any error or warnings generated during the parse, and inform the
-    // debugger about the compiled scripts.
+    // Report any error or warnings generated during the parse.
     for (size_t i = 0; i < parseTask->errors.length(); i++)
         parseTask->errors[i]->throwError(cx);
     if (parseTask->overRecursed)
         ReportOverRecursed(cx);
     if (cx->isExceptionPending())
         return false;
 
     return true;
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -32,16 +32,17 @@
 #include "frontend/BytecodeEmitter.h"
 #include "frontend/SharedContext.h"
 #include "gc/FreeOp.h"
 #include "jit/BaselineJIT.h"
 #include "jit/Ion.h"
 #include "jit/IonCode.h"
 #include "js/MemoryMetrics.h"
 #include "js/Printf.h"
+#include "js/UniquePtr.h"
 #include "js/Utility.h"
 #include "js/Wrapper.h"
 #include "util/StringBuffer.h"
 #include "util/Text.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/BytecodeUtil.h"
 #include "vm/Compression.h"
 #include "vm/Debugger.h"
@@ -1612,17 +1613,19 @@ ScriptSource::chunkChars(JSContext* cx, 
         return nullptr;
     }
     return ret;
 }
 
 ScriptSource::PinnedChars::PinnedChars(JSContext* cx, ScriptSource* source,
                                        UncompressedSourceCache::AutoHoldEntry& holder,
                                        size_t begin, size_t len)
-  : source_(source)
+  : stack_(nullptr),
+    prev_(nullptr),
+    source_(source)
 {
     chars_ = source->chars(cx, holder, begin, len);
     if (chars_) {
         stack_ = &source->pinnedCharsStack_;
         prev_ = *stack_;
         *stack_ = this;
     }
 }
@@ -3446,17 +3449,17 @@ js::detail::CopyScript(JSContext* cx, Ha
     uint32_t nscopes   = src->scopes()->length;
     uint32_t ntrynotes = src->hasTrynotes() ? src->trynotes()->length : 0;
     uint32_t nscopenotes = src->hasScopeNotes() ? src->scopeNotes()->length : 0;
     uint32_t nyieldoffsets = src->hasYieldAndAwaitOffsets() ? src->yieldAndAwaitOffsets().length() : 0;
 
     /* Script data */
 
     size_t size = src->dataSize();
-    ScopedJSFreePtr<uint8_t> data(AllocScriptData(cx->zone(), size));
+    UniquePtr<uint8_t, JS::FreePolicy> data(AllocScriptData(cx->zone(), size));
     if (size && !data) {
         ReportOutOfMemory(cx);
         return false;
     }
 
     /* Scopes */
 
     // The passed in scopes vector contains body scopes that needed to be
@@ -3514,17 +3517,17 @@ js::detail::CopyScript(JSContext* cx, Ha
             }
 
             if (!clone || !objects.append(clone))
                 return false;
         }
     }
 
     /* This assignment must occur before all the Rebase calls. */
-    dst->data = data.forget();
+    dst->data = data.release();
     dst->dataSize_ = size;
     MOZ_ASSERT(bool(dst->data) == bool(src->data));
     if (dst->data)
         memcpy(dst->data, src->data, size);
 
     if (cx->zone() != src->zoneFromAnyThread()) {
         for (size_t i = 0; i < src->scriptData()->natoms(); i++)
             cx->markAtom(src->scriptData()->atoms()[i]);
@@ -4250,30 +4253,33 @@ LazyScript::CreateRaw(JSContext* cx, Han
 
     // Reset runtime flags to obtain a fresh LazyScript.
     p.hasBeenCloned = false;
     p.treatAsRunOnce = false;
 
     size_t bytes = (p.numClosedOverBindings * sizeof(JSAtom*))
                  + (p.numInnerFunctions * sizeof(GCPtrFunction));
 
-    ScopedJSFreePtr<uint8_t> table(bytes ? fun->zone()->pod_malloc<uint8_t>(bytes) : nullptr);
-    if (bytes && !table) {
-        ReportOutOfMemory(cx);
-        return nullptr;
+    UniquePtr<uint8_t, JS::FreePolicy> table;
+    if (bytes) {
+        table.reset(fun->zone()->pod_malloc<uint8_t>(bytes));
+        if (!table) {
+            ReportOutOfMemory(cx);
+            return nullptr;
+        }
     }
 
     LazyScript* res = Allocate<LazyScript>(cx);
     if (!res)
         return nullptr;
 
     cx->realm()->scheduleDelazificationForDebugger();
 
-    return new (res) LazyScript(fun, *sourceObject, table.forget(), packed, sourceStart, sourceEnd,
-                                toStringStart, lineno, column);
+    return new (res) LazyScript(fun, *sourceObject, table.release(), packed, sourceStart,
+                                sourceEnd, toStringStart, lineno, column);
 }
 
 /* static */ LazyScript*
 LazyScript::Create(JSContext* cx, HandleFunction fun,
                    HandleScriptSourceObject sourceObject,
                    const frontend::AtomVector& closedOverBindings,
                    Handle<GCVector<JSFunction*, 8>> innerFunctions,
                    uint32_t sourceStart, uint32_t sourceEnd,
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -2094,16 +2094,17 @@ class JSScript : public js::gc::TenuredC
     {
         JS::RootedScript script_;
         JSContext* cx_;
         bool oldDoNotRelazify_;
       public:
         explicit AutoDelazify(JSContext* cx, JS::HandleFunction fun = nullptr)
             : script_(cx)
             , cx_(cx)
+            , oldDoNotRelazify_(false)
         {
             holdScript(fun);
         }
 
         ~AutoDelazify()
         {
             dropScript();
         }
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -76,34 +76,36 @@ InefficientNonFlatteningStringHashPolicy
 template <typename Char1, typename Char2>
 static bool
 EqualStringsPure(JSString* s1, JSString* s2)
 {
     if (s1->length() != s2->length())
         return false;
 
     const Char1* c1;
-    ScopedJSFreePtr<Char1> ownedChars1;
+    UniquePtr<Char1[], JS::FreePolicy> ownedChars1;
     JS::AutoCheckCannotGC nogc;
     if (s1->isLinear()) {
         c1 = s1->asLinear().chars<Char1>(nogc);
     } else {
-        if (!s1->asRope().copyChars<Char1>(/* tcx */ nullptr, ownedChars1))
+        ownedChars1 = s1->asRope().copyChars<Char1>(/* tcx */ nullptr);
+        if (!ownedChars1)
             MOZ_CRASH("oom");
-        c1 = ownedChars1;
+        c1 = ownedChars1.get();
     }
 
     const Char2* c2;
-    ScopedJSFreePtr<Char2> ownedChars2;
+    UniquePtr<Char2[], JS::FreePolicy> ownedChars2;
     if (s2->isLinear()) {
         c2 = s2->asLinear().chars<Char2>(nogc);
     } else {
-        if (!s2->asRope().copyChars<Char2>(/* tcx */ nullptr, ownedChars2))
+        ownedChars2 = s2->asRope().copyChars<Char2>(/* tcx */ nullptr);
+        if (!ownedChars2)
             MOZ_CRASH("oom");
-        c2 = ownedChars2;
+        c2 = ownedChars2.get();
     }
 
     return EqualChars(c1, c2, s1->length());
 }
 
 /* static */ bool
 InefficientNonFlatteningStringHashPolicy::match(const JSString* const& k, const Lookup& l)
 {
@@ -143,24 +145,25 @@ NotableStringInfo::NotableStringInfo()
 {
 }
 
 template <typename CharT>
 static void
 StoreStringChars(char* buffer, size_t bufferSize, JSString* str)
 {
     const CharT* chars;
-    ScopedJSFreePtr<CharT> ownedChars;
+    UniquePtr<CharT[], JS::FreePolicy> ownedChars;
     JS::AutoCheckCannotGC nogc;
     if (str->isLinear()) {
         chars = str->asLinear().chars<CharT>(nogc);
     } else {
-        if (!str->asRope().copyChars<CharT>(/* tcx */ nullptr, ownedChars))
+        ownedChars = str->asRope().copyChars<CharT>(/* tcx */ nullptr);
+        if (!ownedChars)
             MOZ_CRASH("oom");
-        chars = ownedChars;
+        chars = ownedChars.get();
     }
 
     // We might truncate |str| even if it's much shorter than 1024 chars, if
     // |str| contains unicode chars.  Since this is just for a memory reporter,
     // we don't care.
     PutEscapedString(buffer, bufferSize, chars, str->length(), /* quote */ 0);
 }
 
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -2,26 +2,28 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "vm/ObjectGroup.h"
 
 #include "mozilla/Maybe.h"
+#include "mozilla/Unused.h"
 
 #include "jsexn.h"
 
 #include "builtin/DataViewObject.h"
 #include "gc/FreeOp.h"
 #include "gc/HashUtil.h"
 #include "gc/Policy.h"
 #include "gc/StoreBuffer.h"
 #include "gc/Zone.h"
 #include "js/CharacterEncoding.h"
+#include "js/UniquePtr.h"
 #include "vm/ArrayObject.h"
 #include "vm/JSObject.h"
 #include "vm/RegExpObject.h"
 #include "vm/Shape.h"
 #include "vm/TaggedProto.h"
 
 #include "gc/Marking-inl.h"
 #include "vm/UnboxedObject-inl.h"
@@ -1225,53 +1227,53 @@ ObjectGroup::newPlainObject(JSContext* c
         // will try to use an unboxed layout for the group.
         PreliminaryObjectArrayWithTemplate* preliminaryObjects =
             cx->new_<PreliminaryObjectArrayWithTemplate>(obj->lastProperty());
         if (!preliminaryObjects)
             return nullptr;
         group->setPreliminaryObjects(preliminaryObjects);
         preliminaryObjects->registerNewObject(obj);
 
-        ScopedJSFreePtr<jsid> ids(group->zone()->pod_calloc<jsid>(nproperties));
+        UniquePtr<jsid[], JS::FreePolicy> ids(group->zone()->pod_calloc<jsid>(nproperties));
         if (!ids) {
             ReportOutOfMemory(cx);
             return nullptr;
         }
 
-        ScopedJSFreePtr<TypeSet::Type> types(
+        UniquePtr<TypeSet::Type[], JS::FreePolicy> types(
             group->zone()->pod_calloc<TypeSet::Type>(nproperties));
         if (!types) {
             ReportOutOfMemory(cx);
             return nullptr;
         }
 
         for (size_t i = 0; i < nproperties; i++) {
             ids[i] = properties[i].id;
             types[i] = GetValueTypeForTable(obj->getSlot(i));
             AddTypePropertyId(cx, group, nullptr, IdToTypeId(ids[i]), types[i]);
         }
 
         ObjectGroupRealm::PlainObjectKey key;
-        key.properties = ids;
+        key.properties = ids.get();
         key.nproperties = nproperties;
         MOZ_ASSERT(ObjectGroupRealm::PlainObjectKey::match(key, lookup));
 
         ObjectGroupRealm::PlainObjectEntry entry;
         entry.group.set(group);
         entry.shape.set(obj->lastProperty());
-        entry.types = types;
+        entry.types = types.get();
 
         ObjectGroupRealm::PlainObjectTable::AddPtr np = table->lookupForAdd(lookup);
         if (!table->add(np, key, entry)) {
             ReportOutOfMemory(cx);
             return nullptr;
         }
 
-        ids.forget();
-        types.forget();
+        mozilla::Unused << ids.release();
+        mozilla::Unused << types.release();
 
         return obj;
     }
 
     RootedObjectGroup group(cx, p->value().group);
 
     // AutoSweepObjectGroup checks no GC happens in its scope, so we use Maybe
     // and reset() it before GC calls.
--- a/js/src/vm/ObjectGroup.h
+++ b/js/src/vm/ObjectGroup.h
@@ -623,17 +623,21 @@ class ObjectGroupRealm
 
     // This cache is purged on GC.
     class DefaultNewGroupCache
     {
         ObjectGroup* group_;
         JSObject* associated_;
 
       public:
-        DefaultNewGroupCache() { purge(); }
+        DefaultNewGroupCache()
+          : associated_(nullptr)
+        {
+            purge();
+        }
 
         void purge() {
             group_ = nullptr;
         }
         void put(ObjectGroup* group, JSObject* associated) {
             group_ = group;
             associated_ = associated;
         }
--- a/js/src/vm/RegExpShared.h
+++ b/js/src/vm/RegExpShared.h
@@ -229,17 +229,19 @@ class RegExpShared : public gc::TenuredC
 };
 
 class RegExpZone
 {
     struct Key {
         JSAtom* atom;
         uint16_t flag;
 
-        Key() {}
+        Key()
+          : atom(nullptr), flag(0)
+        { }
         Key(JSAtom* atom, RegExpFlag flag)
           : atom(atom), flag(flag)
         { }
         MOZ_IMPLICIT Key(const ReadBarriered<RegExpShared*>& shared)
           : atom(shared.unbarrieredGet()->getSource()),
             flag(shared.unbarrieredGet()->getFlags())
         { }
 
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2950,24 +2950,24 @@ JSRuntime::initSelfHosting(JSContext* cx
     FillSelfHostingCompileOptions(options);
 
     RootedValue rv(cx);
 
     uint32_t srcLen = GetRawScriptsSize();
 
     const unsigned char* compressed = compressedSources;
     uint32_t compressedLen = GetCompressedSize();
-    ScopedJSFreePtr<char> src(selfHostingGlobal_->zone()->pod_malloc<char>(srcLen));
+    UniqueChars src(selfHostingGlobal_->zone()->pod_malloc<char>(srcLen));
     if (!src || !DecompressString(compressed, compressedLen,
                                   reinterpret_cast<unsigned char*>(src.get()), srcLen))
     {
         return false;
     }
 
-    if (!Evaluate(cx, options, src, srcLen, &rv))
+    if (!Evaluate(cx, options, src.get(), srcLen, &rv))
         return false;
 
     if (!VerifyGlobalNames(cx, shg))
         return false;
 
     return true;
 }
 
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -1519,17 +1519,18 @@ class MutableWrappedPtrOperations<StackS
 
 inline
 Shape::Shape(const StackShape& other, uint32_t nfixed)
   : base_(other.base),
     propid_(other.propid),
     immutableFlags(other.immutableFlags),
     attrs(other.attrs),
     mutableFlags(other.mutableFlags),
-    parent(nullptr)
+    parent(nullptr),
+    listp(nullptr)
 {
     setNumFixedSlots(nfixed);
 
 #ifdef DEBUG
     gc::AllocKind allocKind = getAllocKind();
     MOZ_ASSERT_IF(other.isAccessorShape(), allocKind == gc::AllocKind::ACCESSOR_SHAPE);
     MOZ_ASSERT_IF(allocKind == gc::AllocKind::SHAPE, !other.isAccessorShape());
 #endif
@@ -1553,17 +1554,18 @@ class NurseryShapesRef : public gc::Buff
 
 inline
 Shape::Shape(UnownedBaseShape* base, uint32_t nfixed)
   : base_(base),
     propid_(JSID_EMPTY),
     immutableFlags(SHAPE_INVALID_SLOT | (nfixed << FIXED_SLOTS_SHIFT)),
     attrs(0),
     mutableFlags(0),
-    parent(nullptr)
+    parent(nullptr),
+    listp(nullptr)
 {
     MOZ_ASSERT(base);
     kids.setNull();
 }
 
 inline GetterOp
 Shape::getter() const
 {
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1666,17 +1666,17 @@ class JitActivation : public Activation
     mozilla::Maybe<wasm::TrapData> wasmTrapData_;
 
     void clearRematerializedFrames();
 
 #ifdef CHECK_OSIPOINT_REGISTERS
   protected:
     // Used to verify that live registers don't change between a VM call and
     // the OsiPoint that follows it. Protected to silence Clang warning.
-    uint32_t checkRegs_;
+    uint32_t checkRegs_ = 0;
     RegisterDump regs_;
 #endif
 
   public:
     explicit JitActivation(JSContext* cx);
     ~JitActivation();
 
     bool isProfiling() const {
--- a/js/src/vm/StringType.cpp
+++ b/js/src/vm/StringType.cpp
@@ -274,81 +274,82 @@ AllocChars(JSString* str, size_t length,
     /* Like length, capacity does not include the null char, so take it out. */
     *capacity = numChars - 1;
 
     JS_STATIC_ASSERT(JSString::MAX_LENGTH * sizeof(CharT) < UINT32_MAX);
     *chars = str->zone()->pod_malloc<CharT>(numChars);
     return *chars != nullptr;
 }
 
-bool
-JSRope::copyLatin1CharsZ(JSContext* cx, ScopedJSFreePtr<Latin1Char>& out) const
+UniquePtr<Latin1Char[], JS::FreePolicy>
+JSRope::copyLatin1CharsZ(JSContext* cx) const
 {
-    return copyCharsInternal<Latin1Char>(cx, out, true);
+    return copyCharsInternal<Latin1Char>(cx, true);
 }
 
-bool
-JSRope::copyTwoByteCharsZ(JSContext* cx, ScopedJSFreePtr<char16_t>& out) const
+UniqueTwoByteChars
+JSRope::copyTwoByteCharsZ(JSContext* cx) const
 {
-    return copyCharsInternal<char16_t>(cx, out, true);
+    return copyCharsInternal<char16_t>(cx, true);
 }
 
-bool
-JSRope::copyLatin1Chars(JSContext* cx, ScopedJSFreePtr<Latin1Char>& out) const
+UniquePtr<Latin1Char[], JS::FreePolicy>
+JSRope::copyLatin1Chars(JSContext* cx) const
 {
-    return copyCharsInternal<Latin1Char>(cx, out, false);
+    return copyCharsInternal<Latin1Char>(cx, false);
 }
 
-bool
-JSRope::copyTwoByteChars(JSContext* cx, ScopedJSFreePtr<char16_t>& out) const
+UniqueTwoByteChars
+JSRope::copyTwoByteChars(JSContext* cx) const
 {
-    return copyCharsInternal<char16_t>(cx, out, false);
+    return copyCharsInternal<char16_t>(cx, false);
 }
 
 template <typename CharT>
-bool
-JSRope::copyCharsInternal(JSContext* cx, ScopedJSFreePtr<CharT>& out,
-                          bool nullTerminate) const
+UniquePtr<CharT[], JS::FreePolicy>
+JSRope::copyCharsInternal(JSContext* cx, bool nullTerminate) const
 {
     // Left-leaning ropes are far more common than right-leaning ropes, so
     // perform a non-destructive traversal of the rope, right node first,
     // splatting each node's characters into a contiguous buffer.
 
     size_t n = length();
+
+    UniquePtr<CharT[], JS::FreePolicy> out;
     if (cx)
         out.reset(cx->pod_malloc<CharT>(n + 1));
     else
         out.reset(js_pod_malloc<CharT>(n + 1));
 
     if (!out)
-        return false;
+        return nullptr;
 
     Vector<const JSString*, 8, SystemAllocPolicy> nodeStack;
     const JSString* str = this;
-    CharT* end = out + str->length();
+    CharT* end = out.get() + str->length();
     while (true) {
         if (str->isRope()) {
             if (!nodeStack.append(str->asRope().leftChild()))
-                return false;
+                return nullptr;
             str = str->asRope().rightChild();
         } else {
             end -= str->length();
             CopyChars(end, str->asLinear());
             if (nodeStack.empty())
                 break;
             str = nodeStack.popCopy();
         }
     }
 
-    MOZ_ASSERT(end == out);
+    MOZ_ASSERT(end == out.get());
 
     if (nullTerminate)
         out[n] = 0;
 
-    return true;
+    return out;
 }
 
 template <typename CharT>
 void AddStringToHash(uint32_t* hash, const CharT* chars, size_t len)
 {
     // It's tempting to use |HashString| instead of this loop, but that's
     // slightly different than our existing implementation for non-ropes. We
     // want to pretend we have a contiguous set of chars so we need to
@@ -1497,31 +1498,31 @@ static JSFlatString*
 NewStringDeflated(JSContext* cx, const char16_t* s, size_t n)
 {
     if (JSFlatString* str = TryEmptyOrStaticString(cx, s, n))
         return str;
 
     if (JSInlineString::lengthFits<Latin1Char>(n))
         return NewInlineStringDeflated<allowGC>(cx, mozilla::Range<const char16_t>(s, n));
 
-    ScopedJSFreePtr<Latin1Char> news(cx->pod_malloc<Latin1Char>(n + 1));
+    UniquePtr<Latin1Char[], JS::FreePolicy> news(cx->pod_malloc<Latin1Char>(n + 1));
     if (!news)
         return nullptr;
 
     for (size_t i = 0; i < n; i++) {
         MOZ_ASSERT(s[i] <= JSString::MAX_LATIN1_CHAR);
-        news.get()[i] = Latin1Char(s[i]);
+        news[i] = Latin1Char(s[i]);
     }
     news[n] = '\0';
 
     JSFlatString* str = JSFlatString::new_<allowGC>(cx, news.get(), n);
     if (!str)
         return nullptr;
 
-    news.forget();
+    mozilla::Unused << news.release();
     return str;
 }
 
 template <AllowGC allowGC>
 static JSFlatString*
 NewStringDeflated(JSContext* cx, const Latin1Char* s, size_t n)
 {
     MOZ_CRASH("Shouldn't be called for Latin1 chars");
@@ -1599,31 +1600,31 @@ JSFlatString*
 NewStringCopyNDontDeflate(JSContext* cx, const CharT* s, size_t n)
 {
     if (JSFlatString* str = TryEmptyOrStaticString(cx, s, n))
         return str;
 
     if (JSInlineString::lengthFits<CharT>(n))
         return NewInlineString<allowGC>(cx, mozilla::Range<const CharT>(s, n));
 
-    ScopedJSFreePtr<CharT> news(cx->pod_malloc<CharT>(n + 1));
+    UniquePtr<CharT[], JS::FreePolicy> news(cx->pod_malloc<CharT>(n + 1));
     if (!news) {
         if (!allowGC)
             cx->recoverFromOutOfMemory();
         return nullptr;
     }
 
     PodCopy(news.get(), s, n);
     news[n] = 0;
 
     JSFlatString* str = JSFlatString::new_<allowGC>(cx, news.get(), n);
     if (!str)
         return nullptr;
 
-    news.forget();
+    mozilla::Unused << news.release();
     return str;
 }
 
 template JSFlatString*
 NewStringCopyNDontDeflate<CanGC>(JSContext* cx, const char16_t* s, size_t n);
 
 template JSFlatString*
 NewStringCopyNDontDeflate<NoGC>(JSContext* cx, const char16_t* s, size_t n);
--- a/js/src/vm/StringType.h
+++ b/js/src/vm/StringType.h
@@ -17,16 +17,17 @@
 #include "builtin/String.h"
 #include "gc/Barrier.h"
 #include "gc/Cell.h"
 #include "gc/Heap.h"
 #include "gc/Nursery.h"
 #include "gc/Rooting.h"
 #include "js/CharacterEncoding.h"
 #include "js/RootingAPI.h"
+#include "js/UniquePtr.h"
 #include "util/Text.h"
 #include "vm/Printer.h"
 
 class JSDependentString;
 class JSExtensibleString;
 class JSExternalString;
 class JSInlineString;
 class JSRope;
@@ -661,18 +662,18 @@ class JSString : public js::gc::Cell
     JSString() = delete;
     JSString(const JSString& other) = delete;
     void operator=(const JSString& other) = delete;
 };
 
 class JSRope : public JSString
 {
     template <typename CharT>
-    bool copyCharsInternal(JSContext* cx, js::ScopedJSFreePtr<CharT>& out,
-                           bool nullTerminate) const;
+    js::UniquePtr<CharT[], JS::FreePolicy> copyCharsInternal(JSContext* cx,
+                                                             bool nullTerminate) const;
 
     enum UsingBarrier { WithIncrementalBarrier, NoBarrier };
 
     template<UsingBarrier b, typename CharT>
     JSFlatString* flattenInternal(JSContext* cx);
 
     template<UsingBarrier b>
     JSFlatString* flattenInternal(JSContext* cx);
@@ -684,26 +685,24 @@ class JSRope : public JSString
 
   public:
     template <js::AllowGC allowGC>
     static inline JSRope* new_(JSContext* cx,
                                typename js::MaybeRooted<JSString*, allowGC>::HandleType left,
                                typename js::MaybeRooted<JSString*, allowGC>::HandleType right,
                                size_t length, js::gc::InitialHeap = js::gc::DefaultHeap);
 
-    bool copyLatin1Chars(JSContext* cx,
-                         js::ScopedJSFreePtr<JS::Latin1Char>& out) const;
-    bool copyTwoByteChars(JSContext* cx, js::ScopedJSFreePtr<char16_t>& out) const;
+    js::UniquePtr<JS::Latin1Char[], JS::FreePolicy> copyLatin1Chars(JSContext* cx) const;
+    JS::UniqueTwoByteChars copyTwoByteChars(JSContext* cx) const;
 
-    bool copyLatin1CharsZ(JSContext* cx,
-                          js::ScopedJSFreePtr<JS::Latin1Char>& out) const;
-    bool copyTwoByteCharsZ(JSContext* cx, js::ScopedJSFreePtr<char16_t>& out) const;
+    js::UniquePtr<JS::Latin1Char[], JS::FreePolicy> copyLatin1CharsZ(JSContext* cx) const;
+    JS::UniqueTwoByteChars copyTwoByteCharsZ(JSContext* cx) const;
 
     template <typename CharT>
-    bool copyChars(JSContext* cx, js::ScopedJSFreePtr<CharT>& out) const;
+    js::UniquePtr<CharT[], JS::FreePolicy> copyChars(JSContext* cx) const;
 
     // Hash function specific for ropes that avoids allocating a temporary
     // string. There are still allocations internally so it's technically
     // fallible.
     //
     // Returns the same value as if this were a linear string being hashed.
     MOZ_MUST_USE bool hash(uint32_t* outhHash) const;
 
@@ -1729,28 +1728,27 @@ JSLinearString::chars(const JS::AutoRequ
 template<>
 MOZ_ALWAYS_INLINE const JS::Latin1Char*
 JSLinearString::chars(const JS::AutoRequireNoGC& nogc) const
 {
     return rawLatin1Chars();
 }
 
 template <>
-MOZ_ALWAYS_INLINE bool
-JSRope::copyChars<JS::Latin1Char>(JSContext* cx,
-                                  js::ScopedJSFreePtr<JS::Latin1Char>& out) const
+MOZ_ALWAYS_INLINE js::UniquePtr<JS::Latin1Char[], JS::FreePolicy>
+JSRope::copyChars<JS::Latin1Char>(JSContext* cx) const
 {
-    return copyLatin1Chars(cx, out);
+    return copyLatin1Chars(cx);
 }
 
 template <>
-MOZ_ALWAYS_INLINE bool
-JSRope::copyChars<char16_t>(JSContext* cx, js::ScopedJSFreePtr<char16_t>& out) const
+MOZ_ALWAYS_INLINE JS::UniqueTwoByteChars
+JSRope::copyChars<char16_t>(JSContext* cx) const
 {
-    return copyTwoByteChars(cx, out);
+    return copyTwoByteChars(cx);
 }
 
 template<>
 MOZ_ALWAYS_INLINE bool
 JSThinInlineString::lengthFits<JS::Latin1Char>(size_t length)
 {
     return length <= MAX_LENGTH_LATIN1;
 }
--- a/js/src/vm/TraceLogging.h
+++ b/js/src/vm/TraceLogging.h
@@ -570,32 +570,34 @@ class MOZ_RAII AutoTraceLog
     bool executed;
     AutoTraceLog* prev;
 
   public:
     AutoTraceLog(TraceLoggerThread* logger,
                  const TraceLoggerEvent& event MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : logger(logger),
         isEvent(true),
-        executed(false)
+        executed(false),
+        prev(nullptr)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         payload.event = &event;
         if (logger) {
             logger->startEvent(event);
 
             prev = logger->top;
             logger->top = this;
         }
     }
 
     AutoTraceLog(TraceLoggerThread* logger, TraceLoggerTextId id MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : logger(logger),
         isEvent(false),
-        executed(false)
+        executed(false),
+        prev(nullptr)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         payload.id = id;
         if (logger) {
             logger->startEvent(id);
 
             prev = logger->top;
             logger->top = this;
--- a/js/src/vm/TraceLoggingGraph.h
+++ b/js/src/vm/TraceLoggingGraph.h
@@ -125,16 +125,20 @@ class TraceLoggerGraph
         {
             start_ = start;
             stop_ = stop;
             u.s.textId_ = textId;
             u.s.hasChildren_ = hasChildren;
             nextId_ = nextId;
         }
         TreeEntry()
+          : start_(0),
+            stop_(0),
+            u{},
+            nextId_(0)
         { }
         uint64_t start() {
             return start_;
         }
         uint64_t stop() {
             return stop_;
         }
         uint32_t textId() {
--- a/js/src/vm/TraceLoggingTypes.h
+++ b/js/src/vm/TraceLoggingTypes.h
@@ -157,17 +157,19 @@ class ContinuousSpace {
     uint32_t size_;
     uint32_t capacity_;
 
     // The maximum number of bytes of RAM a continuous space structure can take.
     static const uint32_t LIMIT = 200 * 1024 * 1024;
 
   public:
     ContinuousSpace ()
-     : data_(nullptr)
+     : data_(nullptr),
+       size_(0),
+       capacity_(0)
     { }
 
     bool init() {
         capacity_ = 64;
         size_ = 0;
         data_ = (T*) js_malloc(capacity_ * sizeof(T));
         if (!data_)
             return false;
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -21,16 +21,17 @@
 #include "gc/HashUtil.h"
 #include "jit/BaselineJIT.h"
 #include "jit/CompileInfo.h"
 #include "jit/Ion.h"
 #include "jit/IonAnalysis.h"
 #include "jit/JitRealm.h"
 #include "jit/OptimizationTracking.h"
 #include "js/MemoryMetrics.h"
+#include "js/UniquePtr.h"
 #include "vm/HelperThreads.h"
 #include "vm/JSContext.h"
 #include "vm/JSObject.h"
 #include "vm/JSScript.h"
 #include "vm/Opcodes.h"
 #include "vm/Printer.h"
 #include "vm/Shape.h"
 #include "vm/Time.h"
@@ -3636,17 +3637,17 @@ PreliminaryObjectArrayWithTemplate::mayb
 {
     // Don't perform the analyses until sufficient preliminary objects have
     // been allocated.
     if (!force && !full())
         return;
 
     AutoEnterAnalysis enter(cx);
 
-    ScopedJSDeletePtr<PreliminaryObjectArrayWithTemplate> preliminaryObjects(this);
+    UniquePtr<PreliminaryObjectArrayWithTemplate> preliminaryObjects(this);
     group->detachPreliminaryObjects();
 
     MOZ_ASSERT(shape());
     MOZ_ASSERT(shape()->slotSpan() != 0);
     MOZ_ASSERT(OnlyHasDataProperties(shape()));
 
     // Make sure all the preliminary objects reflect the properties originally
     // in the template object.
@@ -3658,17 +3659,17 @@ PreliminaryObjectArrayWithTemplate::mayb
 
         if (obj->inDictionaryMode() || !OnlyHasDataProperties(obj->lastProperty()))
             return;
 
         if (CommonPrefix(obj->lastProperty(), shape()) != shape())
             return;
     }
 
-    TryConvertToUnboxedLayout(cx, enter, shape(), group, preliminaryObjects);
+    TryConvertToUnboxedLayout(cx, enter, shape(), group, preliminaryObjects.get());
     AutoSweepObjectGroup sweep(group);
     if (group->maybeUnboxedLayout(sweep))
         return;
 
     // We weren't able to use an unboxed layout, but since the preliminary
     // objects still reflect the template object's properties, and all
     // objects in the future will be created with those properties, the
     // properties can be marked as definite for objects in the group.
@@ -3687,41 +3688,41 @@ TypeNewScript::make(JSContext* cx, Objec
     AutoSweepObjectGroup sweep(group);
     MOZ_ASSERT(cx->zone()->types.activeAnalysis);
     MOZ_ASSERT(!group->newScript(sweep));
     MOZ_ASSERT(!group->maybeUnboxedLayout(sweep));
 
     if (group->unknownProperties(sweep))
         return true;
 
-    ScopedJSDeletePtr<TypeNewScript> newScript(cx->new_<TypeNewScript>());
+    auto newScript = cx->make_unique<TypeNewScript>();
     if (!newScript)
         return false;
 
     newScript->function_ = fun;
 
     newScript->preliminaryObjects = group->zone()->new_<PreliminaryObjectArray>();
     if (!newScript->preliminaryObjects)
         return true;
 
-    group->setNewScript(newScript.forget());
+    group->setNewScript(newScript.release());
 
     gc::gcTracer.traceTypeNewScript(group);
     return true;
 }
 
 // Make a TypeNewScript with the same initializer list as |newScript| but with
 // a new template object.
 /* static */ TypeNewScript*
 TypeNewScript::makeNativeVersion(JSContext* cx, TypeNewScript* newScript,
                                  PlainObject* templateObject)
 {
     MOZ_RELEASE_ASSERT(cx->zone()->types.activeAnalysis);
 
-    ScopedJSDeletePtr<TypeNewScript> nativeNewScript(cx->new_<TypeNewScript>());
+    auto nativeNewScript = cx->make_unique<TypeNewScript>();
     if (!nativeNewScript)
         return nullptr;
 
     nativeNewScript->function_ = newScript->function();
     nativeNewScript->templateObject_ = templateObject;
 
     Initializer* cursor = newScript->initializerList;
     while (cursor->kind != Initializer::DONE) { cursor++; }
@@ -3729,17 +3730,17 @@ TypeNewScript::makeNativeVersion(JSConte
 
     nativeNewScript->initializerList = cx->zone()->pod_calloc<Initializer>(initializerLength);
     if (!nativeNewScript->initializerList) {
         ReportOutOfMemory(cx);
         return nullptr;
     }
     PodCopy(nativeNewScript->initializerList, newScript->initializerList, initializerLength);
 
-    return nativeNewScript.forget();
+    return nativeNewScript.release();
 }
 
 size_t
 TypeNewScript::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
 {
     size_t n = mallocSizeOf(this);
     n += mallocSizeOf(preliminaryObjects);
     n += mallocSizeOf(initializerList);
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -25,16 +25,17 @@
 
 #include "builtin/Array.h"
 #include "builtin/DataViewObject.h"
 #include "builtin/TypedObjectConstants.h"
 #include "gc/Barrier.h"
 #include "gc/Marking.h"
 #include "jit/InlinableNatives.h"
 #include "js/Conversions.h"
+#include "js/UniquePtr.h"
 #include "js/Wrapper.h"
 #include "util/Windows.h"
 #include "vm/ArrayBufferObject.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/JSContext.h"
 #include "vm/JSObject.h"
 #include "vm/PIC.h"
@@ -647,33 +648,31 @@ class TypedArrayObjectTemplate : public 
                                   ? GetGCObjectKind(clasp)
                                   : AllocKindForLazyBuffer(nbytes);
         MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, clasp));
         allocKind = GetBackgroundAllocKind(allocKind);
         RootedObjectGroup group(cx, templateObj->group());
 
         NewObjectKind newKind = TenuredObject;
 
-        ScopedJSFreePtr<void> buf;
+        UniquePtr<void, JS::FreePolicy> buf;
         if (!fitsInline && len > 0) {
-            buf = cx->zone()->pod_malloc<uint8_t>(nbytes);
+            buf.reset(cx->zone()->pod_calloc<uint8_t>(nbytes));
             if (!buf) {
                 ReportOutOfMemory(cx);
                 return nullptr;
             }
-
-            memset(buf, 0, nbytes);
         }
 
         TypedArrayObject* obj = NewObjectWithGroup<TypedArrayObject>(cx, group, allocKind, newKind);
         if (!obj)
             return nullptr;
 
         initTypedArraySlots(obj, len);
-        initTypedArrayData(cx, obj, len, buf.forget(), allocKind);
+        initTypedArrayData(cx, obj, len, buf.release(), allocKind);
 
         return obj;
     }
 
     // ES2018 draft rev 8340bf9a8427ea81bb0d1459471afbcc91d18add
     // 22.2.4.1 TypedArray ( )
     // 22.2.4.2 TypedArray ( length )
     // 22.2.4.3 TypedArray ( typedArray )
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -333,16 +333,17 @@ struct js::AsmJSMetadata : Metadata, Asm
     }
     uint32_t srcEndAfterCurly() const {
         return srcStart + srcLengthWithRightBrace;
     }
 
     AsmJSMetadata()
       : Metadata(ModuleKind::AsmJS),
         cacheResult(CacheResult::Miss),
+        toStringStart(0),
         srcStart(0),
         strict(false)
     {}
     ~AsmJSMetadata() override {}
 
     const AsmJSExport& lookupAsmJSExport(uint32_t funcIndex) const {
         // The AsmJSExportVector isn't stored in sorted order so do a linear
         // search. This is for the super-cold and already-expensive toString()
@@ -1519,17 +1520,17 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED Modu
                 SimdType type_;
                 SimdOperation which_;
             } simdOp;
 
             // |varOrConst|, through |varOrConst.literalValue_|, has a
             // non-trivial constructor and therefore MUST be placement-new'd
             // into existence.
             MOZ_PUSH_DISABLE_NONTRIVIAL_UNION_WARNINGS
-            U() {}
+            U() : funcDefIndex_(0) {}
             MOZ_POP_DISABLE_NONTRIVIAL_UNION_WARNINGS
         } u;
 
         friend class ModuleValidator;
         friend class js::LifoAlloc;
 
         explicit Global(Which which) : which_(which) {}
 
@@ -1610,17 +1611,17 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED Modu
         enum Kind { Function, Constant };
         Kind kind;
 
         union {
             double cst;
             AsmJSMathBuiltinFunction func;
         } u;
 
-        MathBuiltin() : kind(Kind(-1)) {}
+        MathBuiltin() : kind(Kind(-1)), u{} {}
         explicit MathBuiltin(double cst) : kind(Constant) {
             u.cst = cst;
         }
         explicit MathBuiltin(AsmJSMathBuiltinFunction func) : kind(Function) {
             u.func = func;
         }
     };
 
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -1005,16 +1005,18 @@ using ScratchI8 = ScratchI32;
 BaseLocalIter::BaseLocalIter(const ValTypeVector& locals, size_t argsLength, bool debugEnabled)
   : locals_(locals),
     argsLength_(argsLength),
     argsRange_(locals.begin(), argsLength),
     argsIter_(argsRange_),
     index_(0),
     localSize_(debugEnabled ? DebugFrame::offsetOfFrame() : 0),
     reservedSize_(localSize_),
+    frameOffset_(0),
+    mirType_(MIRType::Undefined),
     done_(false)
 {
     MOZ_ASSERT(argsLength <= locals.length());
     settle();
 }
 
 int32_t
 BaseLocalIter::pushLocal(size_t nbytes)
--- a/js/src/wasm/WasmFrameIter.cpp
+++ b/js/src/wasm/WasmFrameIter.cpp
@@ -35,17 +35,18 @@ using mozilla::Maybe;
 
 WasmFrameIter::WasmFrameIter(JitActivation* activation, wasm::Frame* fp)
   : activation_(activation),
     code_(nullptr),
     codeRange_(nullptr),
     lineOrBytecode_(0),
     fp_(fp ? fp : activation->wasmExitFP()),
     unwoundIonCallerFP_(nullptr),
-    unwind_(Unwind::False)
+    unwind_(Unwind::False),
+    unwoundAddressOfReturnAddress_(nullptr)
 {
     MOZ_ASSERT(fp_);
 
     // When the stack is captured during a trap (viz., to create the .stack
     // for an Error object), use the pc/bytecode information captured by the
     // signal handler in the runtime.
 
     if (activation->isWasmTrapping()) {
--- a/js/src/wasm/WasmFrameIter.h
+++ b/js/src/wasm/WasmFrameIter.h
@@ -94,32 +94,35 @@ class WasmFrameIter
 enum class SymbolicAddress;
 
 // An ExitReason describes the possible reasons for leaving compiled wasm
 // code or the state of not having left compiled wasm code
 // (ExitReason::None). It is either a known reason, or a enumeration to a native
 // function that is used for better display in the profiler.
 class ExitReason
 {
-    uint32_t payload_;
-
-    ExitReason() {}
-
   public:
     enum class Fixed : uint32_t
     {
         None,            // default state, the pc is in wasm code
         FakeInterpEntry, // slow-path entry call from C++ WasmCall()
         ImportJit,       // fast-path call directly into JIT code
         ImportInterp,    // slow-path call into C++ Invoke()
         BuiltinNative,   // fast-path call directly into native C++ code
         Trap,            // call to trap handler
         DebugTrap        // call to debug trap handler
     };
 
+  private:
+    uint32_t payload_;
+
+    ExitReason() : ExitReason(Fixed::None) {}
+
+  public:
+
     MOZ_IMPLICIT ExitReason(Fixed exitReason)
       : payload_(0x0 | (uint32_t(exitReason) << 1))
     {
         MOZ_ASSERT(isFixed());
         MOZ_ASSERT_IF(isNone(), payload_ == 0);
     }
 
     explicit ExitReason(SymbolicAddress sym)
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -2887,16 +2887,17 @@ class CompileStreamTask : public Promise
     CompileStreamTask(JSContext* cx, Handle<PromiseObject*> promise,
                       CompileArgs& compileArgs, bool instantiate,
                       HandleObject importObj)
       : PromiseHelperTask(cx, promise),
         compileArgs_(&compileArgs),
         instantiate_(instantiate),
         importObj_(cx, importObj),
         streamState_(mutexid::WasmStreamStatus, Env),
+        codeSection_{},
         codeStreamEnd_(nullptr),
         exclusiveCodeStreamEnd_(mutexid::WasmCodeStreamEnd, nullptr),
         exclusiveTailBytes_(mutexid::WasmTailBytesPtr, nullptr),
         streamFailed_(false)
     {
         MOZ_ASSERT_IF(importObj_, instantiate_);
     }
 };
--- a/js/src/wasm/WasmOpIter.h
+++ b/js/src/wasm/WasmOpIter.h
@@ -233,16 +233,18 @@ Classify(OpBytes op);
 template <typename Value>
 struct LinearMemoryAddress
 {
     Value base;
     uint32_t offset;
     uint32_t align;
 
     LinearMemoryAddress()
+      : offset(0),
+        align(0)
     {}
     LinearMemoryAddress(Value base, uint32_t offset, uint32_t align)
       : base(base), offset(offset), align(align)
     {}
 };
 
 template <typename ControlItem>
 class ControlStackEntry
--- a/js/src/wasm/WasmTextToBinary.cpp
+++ b/js/src/wasm/WasmTextToBinary.cpp
@@ -164,17 +164,18 @@ class WasmToken
       : kind_(Kind::Invalid),
         begin_(nullptr),
         end_(nullptr),
         u()
     { }
     WasmToken(Kind kind, const char16_t* begin, const char16_t* end)
       : kind_(kind),
         begin_(begin),
-        end_(end)
+        end_(end),
+        u{}
     {
         MOZ_ASSERT(kind_ != Error);
         MOZ_ASSERT(kind_ != Invalid);
         MOZ_ASSERT((kind == EndOfFile) == (begin == end));
     }
     explicit WasmToken(uint32_t index, const char16_t* begin, const char16_t* end)
       : kind_(Index),
         begin_(begin),
@@ -247,17 +248,18 @@ class WasmToken
         MOZ_ASSERT(begin != end);
         MOZ_ASSERT(kind_ == AtomicCmpXchg || kind_ == AtomicLoad || kind_ == AtomicRMW ||
                    kind_ == AtomicStore || kind_ == Wait || kind_ == Wake);
         u.threadOp_ = op;
     }
     explicit WasmToken(const char16_t* begin)
       : kind_(Error),
         begin_(begin),
-        end_(begin)
+        end_(begin),
+        u{}
     {}
     Kind kind() const {
         MOZ_ASSERT(kind_ != Kind::Invalid);
         return kind_;
     }
     const char16_t* begin() const {
         return begin_;
     }
--- a/js/src/wasm/WasmTypes.h
+++ b/js/src/wasm/WasmTypes.h
@@ -792,17 +792,17 @@ class InitExpr
   private:
     Kind kind_;
     union U {
         Val val_;
         struct {
             uint32_t index_;
             ValType type_;
         } global;
-        U() {}
+        U() : global{} {}
     } u;
 
   public:
     InitExpr() = default;
 
     explicit InitExpr(Val val) : kind_(Kind::Constant) {
         u.val_ = val;
     }
@@ -915,17 +915,17 @@ class GlobalDesc
     union V {
         struct {
             union U {
                 InitExpr initial_;
                 struct {
                     ValType type_;
                     uint32_t index_;
                 } import;
-                U() {}
+                U() : import{} {}
             } val;
             unsigned offset_;
             bool isMutable_;
             bool isWasm_;
             bool isExport_;
         } var;
         Val cst_;
         V() {}
@@ -1595,17 +1595,20 @@ class CallSiteDesc
     enum Kind {
         Func,       // pc-relative call to a specific function
         Dynamic,    // dynamic callee called via register
         Symbolic,   // call to a single symbolic callee
         EnterFrame, // call to a enter frame handler
         LeaveFrame, // call to a leave frame handler
         Breakpoint  // call to instruction breakpoint
     };
-    CallSiteDesc() {}
+    CallSiteDesc()
+      : lineOrBytecode_(0),
+        kind_(0)
+    {}
     explicit CallSiteDesc(Kind kind)
       : lineOrBytecode_(0), kind_(kind)
     {
         MOZ_ASSERT(kind == Kind(kind_));
     }
     CallSiteDesc(uint32_t lineOrBytecode, Kind kind)
       : lineOrBytecode_(lineOrBytecode), kind_(kind)
     {
@@ -1616,17 +1619,17 @@ class CallSiteDesc
     Kind kind() const { return Kind(kind_); }
 };
 
 class CallSite : public CallSiteDesc
 {
     uint32_t returnAddressOffset_;
 
   public:
-    CallSite() {}
+    CallSite() : returnAddressOffset_(0) {}
 
     CallSite(CallSiteDesc desc, uint32_t returnAddressOffset)
       : CallSiteDesc(desc),
         returnAddressOffset_(returnAddressOffset)
     { }
 
     void offsetBy(int32_t delta) { returnAddressOffset_ += delta; }
     uint32_t returnAddressOffset() const { return returnAddressOffset_; }
@@ -1994,17 +1997,17 @@ class CalleeDesc
         // Like Builtin, but automatically passes Instance* as first argument.
         BuiltinInstanceMethod
     };
 
   private:
     // which_ shall be initialized in the static constructors
     MOZ_INIT_OUTSIDE_CTOR Which which_;
     union U {
-        U() {}
+        U() : funcIndex_(0) {}
         uint32_t funcIndex_;
         struct {
             uint32_t globalDataOffset_;
         } import;
         struct {
             uint32_t globalDataOffset_;
             uint32_t minLength_;
             bool external_;
--- a/netwerk/base/nsITimedChannel.idl
+++ b/netwerk/base/nsITimedChannel.idl
@@ -31,18 +31,22 @@ interface nsITimedChannel : nsISupports 
   // channelCreationTime will be available even with this attribute set to
   // false.
   attribute boolean timingEnabled;
 
   // The number of redirects
   attribute uint8_t redirectCount;
   attribute uint8_t internalRedirectCount;
 
-  [noscript] readonly attribute TimeStamp channelCreation;
-  [noscript] readonly attribute TimeStamp asyncOpen;
+  // These properties should only be written externally when they must be
+  // propagated across an internal redirect.  For example, when a service
+  // worker interception falls back to network we need to copy the original
+  // timing values to the new nsHttpChannel.
+  [noscript] attribute TimeStamp channelCreation;
+  [noscript] attribute TimeStamp asyncOpen;
 
   // The following are only set when the request is intercepted by a service
   // worker no matter the response is synthesized.
   [noscript] attribute TimeStamp launchServiceWorkerStart;
   [noscript] attribute TimeStamp launchServiceWorkerEnd;
   [noscript] attribute TimeStamp dispatchFetchEventStart;
   [noscript] attribute TimeStamp dispatchFetchEventEnd;
   [noscript] attribute TimeStamp handleFetchEventStart;
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -196,16 +196,17 @@ HttpBaseChannel::HttpBaseChannel()
   , mInitialRwin(0)
   , mProxyResolveFlags(0)
   , mContentDispositionHint(UINT32_MAX)
   , mHttpHandler(gHttpHandler)
   , mReferrerPolicy(NS_GetDefaultReferrerPolicy())
   , mRedirectCount(0)
   , mInternalRedirectCount(0)
   , mChannelCreationTime(0)
+  , mAsyncOpenTimeOverriden(false)
   , mForcePending(false)
   , mCorsIncludeCredentials(false)
   , mCorsMode(nsIHttpChannelInternal::CORS_MODE_NO_CORS)
   , mRedirectMode(nsIHttpChannelInternal::REDIRECT_MODE_FOLLOW)
   , mOnStartRequestCalled(false)
   , mOnStopRequestCalled(false)
   , mUpgradableToSecure(true)
   , mAfterOnStartRequestBegun(false)
@@ -3779,24 +3780,38 @@ HttpBaseChannel::SetupReplacementChannel
         std::max(newCount, mInternalRedirectCount));
     } else {
       int8_t newCount = mRedirectCount + 1;
       newTimedChannel->SetRedirectCount(
         std::max(newCount, mRedirectCount));
       newTimedChannel->SetInternalRedirectCount(mInternalRedirectCount);
     }
 
+    TimeStamp oldAsyncOpenTime;
+    oldTimedChannel->GetAsyncOpen(&oldAsyncOpenTime);
+
+    if (redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
+      TimeStamp oldChannelCreationTimestamp;
+      oldTimedChannel->GetChannelCreation(&oldChannelCreationTimestamp);
+
+      if (!oldChannelCreationTimestamp.IsNull()) {
+        newTimedChannel->SetChannelCreation(oldChannelCreationTimestamp);
+      }
+
+      if (!oldAsyncOpenTime.IsNull()) {
+        newTimedChannel->SetAsyncOpen(oldAsyncOpenTime);
+      }
+    }
+
     // If the RedirectStart is null, we will use the AsyncOpen value of the
     // previous channel (this is the first redirect in the redirects chain).
     if (mRedirectStartTimeStamp.IsNull()) {
       // Only do this for real redirects.  Internal redirects should be hidden.
       if (!(redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
-        TimeStamp asyncOpen;
-        oldTimedChannel->GetAsyncOpen(&asyncOpen);
-        newTimedChannel->SetRedirectStart(asyncOpen);
+        newTimedChannel->SetRedirectStart(oldAsyncOpenTime);
       }
     } else {
       newTimedChannel->SetRedirectStart(mRedirectStartTimeStamp);
     }
 
     // For internal redirects just propagate the last redirect end time
     // forward.  Otherwise the new redirect end time is the last response
     // end time.
@@ -3924,21 +3939,38 @@ HttpBaseChannel::GetTimingEnabled(bool* 
 
 NS_IMETHODIMP
 HttpBaseChannel::GetChannelCreation(TimeStamp* _retval) {
   *_retval = mChannelCreationTimestamp;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+HttpBaseChannel::SetChannelCreation(TimeStamp aValue) {
+  MOZ_DIAGNOSTIC_ASSERT(!aValue.IsNull());
+  TimeDuration adjust = aValue - mChannelCreationTimestamp;
+  mChannelCreationTimestamp = aValue;
+  mChannelCreationTime += (PRTime)adjust.ToMicroseconds();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 HttpBaseChannel::GetAsyncOpen(TimeStamp* _retval) {
   *_retval = mAsyncOpenTime;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+HttpBaseChannel::SetAsyncOpen(TimeStamp aValue) {
+  MOZ_DIAGNOSTIC_ASSERT(!aValue.IsNull());
+  mAsyncOpenTime = aValue;
+  mAsyncOpenTimeOverriden = true;
+  return NS_OK;
+}
+
 /**
  * @return the number of redirects. There is no check for cross-domain
  * redirects. This check must be done by the consumers.
  */
 NS_IMETHODIMP
 HttpBaseChannel::GetRedirectCount(uint8_t *aRedirectCount)
 {
   *aRedirectCount = mRedirectCount;
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -671,16 +671,17 @@ protected:
   TimeStamp                         mDispatchFetchEventStart;
   TimeStamp                         mDispatchFetchEventEnd;
   TimeStamp                         mHandleFetchEventStart;
   TimeStamp                         mHandleFetchEventEnd;
   // copied from the transaction before we null out mTransaction
   // so that the timing can still be queried from OnStopRequest
   TimingStruct                      mTransactionTimings;
 
+  bool                              mAsyncOpenTimeOverriden;
   bool                              mForcePending;
 
   bool mCorsIncludeCredentials;
   uint32_t mCorsMode;
   uint32_t mRedirectMode;
 
   // These parameters are used to ensure that we do not call OnStartRequest and
   // OnStopRequest more than once.
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -2497,17 +2497,20 @@ HttpChannelChild::AsyncOpen(nsIStreamLis
   NS_ENSURE_ARG_POINTER(listener);
   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
 
   if (MaybeWaitForUploadStreamLength(listener, aContext)) {
     return NS_OK;
   }
 
-  mAsyncOpenTime = TimeStamp::Now();
+  if (!mAsyncOpenTimeOverriden) {
+    mAsyncOpenTime = TimeStamp::Now();
+  }
+
 #ifdef MOZ_TASK_TRACER
   if (tasktracer::IsStartLogging()) {
     nsCOMPtr<nsIURI> uri;
     GetURI(getter_AddRefs(uri));
     nsAutoCString urispec;
     uri->GetSpec(urispec);
     tasktracer::AddLabel("HttpChannelChild::AsyncOpen %s", urispec.get());
   }
--- a/netwerk/protocol/http/InterceptedHttpChannel.cpp
+++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp
@@ -680,16 +680,26 @@ InterceptedHttpChannel::ResetInterceptio
                                       nullptr, // aLoadGroup
                                       nullptr, // aCallbacks
                                       mLoadFlags);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = SetupReplacementChannel(mURI, newChannel, true, flags);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  nsCOMPtr<nsITimedChannel> newTimedChannel = do_QueryInterface(newChannel);
+  if (newTimedChannel) {
+    if (!mAsyncOpenTime.IsNull()) {
+      newTimedChannel->SetAsyncOpen(mAsyncOpenTime);
+    }
+    if (!mChannelCreationTimestamp.IsNull()) {
+      newTimedChannel->SetChannelCreation(mChannelCreationTimestamp);
+    }
+  }
+
   if (mRedirectMode != nsIHttpChannelInternal::REDIRECT_MODE_MANUAL) {
     nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
     rv = newChannel->GetLoadFlags(&loadFlags);
     NS_ENSURE_SUCCESS(rv, rv);
     loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
     rv = newChannel->SetLoadFlags(loadFlags);
     NS_ENSURE_SUCCESS(rv, rv);
   }
--- a/netwerk/protocol/http/NullHttpChannel.cpp
+++ b/netwerk/protocol/http/NullHttpChannel.cpp
@@ -606,23 +606,39 @@ NullHttpChannel::SetInternalRedirectCoun
 NS_IMETHODIMP
 NullHttpChannel::GetChannelCreation(mozilla::TimeStamp *aChannelCreation)
 {
   *aChannelCreation = mChannelCreationTimestamp;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+NullHttpChannel::SetChannelCreation(TimeStamp aValue) {
+  MOZ_DIAGNOSTIC_ASSERT(!aValue.IsNull());
+  TimeDuration adjust = aValue - mChannelCreationTimestamp;
+  mChannelCreationTimestamp = aValue;
+  mChannelCreationTime += (PRTime)adjust.ToMicroseconds();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 NullHttpChannel::GetAsyncOpen(mozilla::TimeStamp *aAsyncOpen)
 {
   *aAsyncOpen = mAsyncOpenTime;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+NullHttpChannel::SetAsyncOpen(TimeStamp aValue) {
+  MOZ_DIAGNOSTIC_ASSERT(!aValue.IsNull());
+  mAsyncOpenTime = aValue;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 NullHttpChannel::GetLaunchServiceWorkerStart(mozilla::TimeStamp *_retval)
 {
   MOZ_ASSERT(_retval);
   *_retval = mAsyncOpenTime;
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -6045,17 +6045,19 @@ nsHttpChannel::AsyncOpen(nsIStreamListen
 
     if (mLoadGroup)
         mLoadGroup->AddRequest(this, nullptr);
 
     // record asyncopen time unconditionally and clear it if we
     // don't want it after OnModifyRequest() weighs in. But waiting for
     // that to complete would mean we don't include proxy resolution in the
     // timing.
-    mAsyncOpenTime = TimeStamp::Now();
+    if (!mAsyncOpenTimeOverriden) {
+      mAsyncOpenTime = TimeStamp::Now();
+    }
 
     // Remember we have Authorization header set here.  We need to check on it
     // just once and early, AsyncOpen is the best place.
     mCustomAuthHeader = mRequestHead.HasHeader(nsHttp::Authorization);
 
     // The common case for HTTP channels is to begin proxy resolution and return
     // at this point. The only time we know mProxyInfo already is if we're
     // proxying a non-http protocol like ftp. We don't need to discover proxy
--- a/toolkit/components/filewatcher/NativeFileWatcherWin.cpp
+++ b/toolkit/components/filewatcher/NativeFileWatcherWin.cpp
@@ -13,16 +13,17 @@
 #include "mozilla/UniquePtr.h"
 #include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
 #include "nsIFile.h"
 #include "nsIObserverService.h"
 #include "nsProxyRelease.h"
 #include "nsTArray.h"
 #include "mozilla/Logging.h"
+#include "mozilla/Scoped.h"
 
 namespace mozilla {
 
 // Enclose everything which is not exported in an anonymous namespace.
 namespace {
 
 /**
  * An event used to notify the main thread when an error happens.