Bug 1492584, part 2 - Make mozJSComponentLoader::sSelf a strong reference. r=kmag
authorAndrew McCreight <continuation@gmail.com>
Tue, 23 Oct 2018 23:19:34 +0000
changeset 491184 2df4dcfce65f9a9a0e41d3f65390c614d147cc1b
parent 491183 70984251b17425dc35f140dbca8097064184afc5
child 491185 2c675ab661cad80e1cc5a791de042a3322110adc
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewerskmag
bugs1492584
milestone65.0a1
Bug 1492584, part 2 - Make mozJSComponentLoader::sSelf a strong reference. r=kmag The JS component loader is an XPCOM component, so it is held alive by the component manager. In order to be able to make it no longer be an XPCOM component, we have to keep it alive some other way. I decided to simply keep it alive as long as XPConnect itself is alive. Depends on D9583 Differential Revision: https://phabricator.services.mozilla.com/D8757
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSComponentLoader.h
js/xpconnect/src/nsXPConnect.cpp
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -306,17 +306,17 @@ mozJSComponentLoader::~mozJSComponentLoa
     if (mInitialized) {
         NS_ERROR("'xpcom-shutdown-loaders' was not fired before cleaning up mozJSComponentLoader");
         UnloadModules();
     }
 
     sSelf = nullptr;
 }
 
-mozJSComponentLoader*
+StaticRefPtr<mozJSComponentLoader>
 mozJSComponentLoader::sSelf;
 
 NS_IMPL_ISUPPORTS(mozJSComponentLoader,
                   nsIObserver)
 
 nsresult
 mozJSComponentLoader::ReallyInit()
 {
@@ -535,16 +535,30 @@ mozJSComponentLoader::FindTargetObject(J
     // instead. This is needed when calling the subscript loader within a frame
     // script, since it the FrameScript NSVO will have been found.
     if (!aTargetObject ||
         !IsLoaderGlobal(JS::GetNonCCWObjectGlobal(aTargetObject))) {
         aTargetObject.set(CurrentGlobalOrNull(aCx));
     }
 }
 
+void
+mozJSComponentLoader::InitStatics()
+{
+    MOZ_ASSERT(!sSelf);
+    sSelf = new mozJSComponentLoader();
+}
+
+void
+mozJSComponentLoader::Shutdown()
+{
+    MOZ_ASSERT(sSelf);
+    sSelf = nullptr;
+}
+
 // This requires that the keys be strings and the values be pointers.
 template <class Key, class Data, class UserData>
 static size_t
 SizeOfTableExcludingThis(const nsBaseHashtable<Key, Data, UserData>& aTable,
                          MallocSizeOf aMallocSizeOf)
 {
     size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
     for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
--- a/js/xpconnect/loader/mozJSComponentLoader.h
+++ b/js/xpconnect/loader/mozJSComponentLoader.h
@@ -6,16 +6,17 @@
 
 #ifndef mozJSComponentLoader_h
 #define mozJSComponentLoader_h
 
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/FileLocation.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Module.h"
+#include "mozilla/StaticPtr.h"
 #include "nsAutoPtr.h"
 #include "nsISupports.h"
 #include "nsIObserver.h"
 #include "nsIURI.h"
 #include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
 #include "jsapi.h"
 
@@ -54,19 +55,25 @@ class mozJSComponentLoader final : publi
     nsresult GetModuleImportStack(const nsACString& aLocation, nsACString& aRetval);
     nsresult GetComponentLoadStack(const nsACString& aLocation, nsACString& aRetval);
 
     const mozilla::Module* LoadModule(mozilla::FileLocation& aFile);
 
     void FindTargetObject(JSContext* aCx,
                           JS::MutableHandleObject aTargetObject);
 
+    static void InitStatics();
+    static void Shutdown();
+
     static already_AddRefed<mozJSComponentLoader> GetOrCreate();
 
-    static mozJSComponentLoader* Get() { return sSelf; }
+    static mozJSComponentLoader* Get() {
+        MOZ_ASSERT(sSelf, "Should have already created the component loader");
+        return sSelf;
+    }
 
     nsresult ImportInto(const nsACString& aResourceURI, JS::HandleValue aTargetObj,
                         JSContext* aCx, uint8_t aArgc, JS::MutableHandleValue aRetval);
 
     nsresult Import(JSContext* aCx, const nsACString& aResourceURI,
                     JS::MutableHandleObject aModuleGlobal,
                     JS::MutableHandleObject aModuleExports,
                     bool aIgnoreExports = false);
@@ -96,17 +103,17 @@ class mozJSComponentLoader final : publi
     {
         if (mLoaderGlobal) {
             return mLoaderGlobal;
         }
         return GetSharedGlobal(aCx);
     }
 
  private:
-    static mozJSComponentLoader* sSelf;
+    static mozilla::StaticRefPtr<mozJSComponentLoader> sSelf;
 
     nsresult ReallyInit();
     void UnloadModules();
 
     void CreateLoaderGlobal(JSContext* aCx,
                             const nsACString& aLocation,
                             JS::MutableHandleObject aGlobal);
 
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -147,27 +147,31 @@ nsXPConnect::InitStatics()
         MOZ_CRASH("InitSelfHostedCode failed");
     }
     if (!gSelf->mRuntime->InitializeStrings(cx)) {
         MOZ_CRASH("InitializeStrings failed");
     }
 
     // Initialize our singleton scopes.
     gSelf->mRuntime->InitSingletonScopes();
+
+    mozJSComponentLoader::InitStatics();
 }
 
 // static
 void
 nsXPConnect::ReleaseXPConnectSingleton()
 {
     nsXPConnect* xpc = gSelf;
     if (xpc) {
         nsrefcnt cnt;
         NS_RELEASE2(xpc, cnt);
     }
+
+    mozJSComponentLoader::Shutdown();
 }
 
 // static
 XPCJSRuntime*
 nsXPConnect::GetRuntimeInstance()
 {
     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     return gSelf->mRuntime;