Bug 1366402: Use AutoMemMap helper in mozJSComponentLoader. r?mccr8 draft
authorKris Maglione <maglione.k@gmail.com>
Sat, 20 May 2017 12:20:35 -0700
changeset 582009 88a338ef9a88ff0b775f3f31600f32892b932940
parent 580621 e46cf2cfc3495b13fd4b7aac12b179712233f454
child 629648 b0cd747a6b8b2f4d82b51a844c455ff554aa9ad1
push id59949
push usermaglione.k@gmail.com
push dateSat, 20 May 2017 19:25:42 +0000
reviewersmccr8
bugs1366402, 989373
milestone55.0a1
Bug 1366402: Use AutoMemMap helper in mozJSComponentLoader. r?mccr8 This helper is already being used in the script preloader, and encapsulates all of the memory mapping and RAII logic used to do the same in the component loader. Reusing it there allows us to remove a lot of redundant code. This is applied on top of the patches for bug 989373 in order to avoid conflicts. MozReview-Commit-ID: AJ26qV4JLci
js/xpconnect/loader/ScriptPreloader-inl.h
js/xpconnect/loader/mozJSComponentLoader.cpp
--- a/js/xpconnect/loader/ScriptPreloader-inl.h
+++ b/js/xpconnect/loader/ScriptPreloader-inl.h
@@ -15,16 +15,32 @@
 #include "mozilla/Unused.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 #include <prio.h>
 
 namespace mozilla {
+
+// A specialization of GenericErrorResult which auto-converts to a nsresult.
+// This should be removed when bug 1366511 is fixed.
+template <>
+class MOZ_MUST_USE_TYPE GenericErrorResult<nsresult>
+{
+  nsresult mErrorValue;
+
+  template<typename V, typename E2> friend class Result;
+
+public:
+  explicit GenericErrorResult(nsresult aErrorValue) : mErrorValue(aErrorValue) {}
+
+  operator nsresult() { return mErrorValue; }
+};
+
 namespace loader {
 
 using mozilla::dom::AutoJSAPI;
 
 struct MOZ_RAII AutoSafeJSAPI : public AutoJSAPI
 {
     AutoSafeJSAPI() { Init(); }
 };
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -34,28 +34,32 @@
 #include "nsJSPrincipals.h"
 #include "nsJSUtils.h"
 #include "xpcprivate.h"
 #include "xpcpublic.h"
 #include "nsContentUtils.h"
 #include "nsXULAppAPI.h"
 #include "WrapperFactory.h"
 
+#include "AutoMemMap.h"
+#include "ScriptPreloader-inl.h"
+
 #include "mozilla/AddonPathService.h"
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/scache/StartupCacheUtils.h"
 #include "mozilla/MacroForEach.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ScriptPreloader.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/UniquePtrExtensions.h"
 #include "mozilla/Unused.h"
 
 using namespace mozilla;
 using namespace mozilla::scache;
+using namespace mozilla::loader;
 using namespace xpc;
 using namespace JS;
 
 static const char kObserverServiceContractID[] = "@mozilla.org/observer-service;1";
 static const char kJSCachePrefix[] = "jsloader";
 
 /**
  * Buffer sizes for serialization and deserialization of scripts.
@@ -501,35 +505,16 @@ mozJSComponentLoader::CreateLoaderGlobal
     if (!JS_DefineFunctions(aCx, global, gGlobalFun) ||
         !JS_DefineProfilingFunctions(aCx, global)) {
         return;
     }
 
     aGlobal.set(global);
 }
 
-// Some stack based classes for cleaning up on early return
-class FileAutoCloser
-{
- public:
-    explicit FileAutoCloser(PRFileDesc* file) : mFile(file) {}
-    ~FileAutoCloser() { PR_Close(mFile); }
- private:
-    PRFileDesc* mFile;
-};
-
-class FileMapAutoCloser
-{
- public:
-    explicit FileMapAutoCloser(PRFileMap* map) : mMap(map) {}
-    ~FileMapAutoCloser() { PR_CloseFileMap(mMap); }
- private:
-    PRFileMap* mMap;
-};
-
 JSObject*
 mozJSComponentLoader::PrepareObjectForLocation(JSContext* aCx,
                                                nsIFile* aComponentFile,
                                                nsIURI* aURI,
                                                bool* aRealFile)
 {
     RootedObject globalObj(aCx);
 
@@ -665,62 +650,21 @@ mozJSComponentLoader::ObjectForLocation(
         // See bug 1303754.
         CompileOptions options(cx);
         options.setNoScriptRval(true)
                .setVersion(JSVERSION_LATEST)
                .setFileAndLine(nativePath.get(), 1)
                .setSourceIsLazy(!!cache);
 
         if (realFile) {
-            int64_t fileSize;
-            rv = aComponentFile->GetFileSize(&fileSize);
-            if (NS_FAILED(rv)) {
-                return rv;
-            }
-
-            int64_t maxSize = UINT32_MAX;
-            if (fileSize > maxSize) {
-                NS_ERROR("file too large");
-                return NS_ERROR_FAILURE;
-            }
-
-            PRFileDesc* fileHandle;
-            rv = aComponentFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fileHandle);
-            if (NS_FAILED(rv)) {
-                return NS_ERROR_FILE_NOT_FOUND;
-            }
-
-            // Make sure the file is closed, no matter how we return.
-            FileAutoCloser fileCloser(fileHandle);
+            AutoMemMap map;
+            MOZ_TRY(map.init(aComponentFile));
 
-            // We don't provide the file size here.  If we did, PR_CreateFileMap
-            // would simply stat() the file to verify that the size we provided
-            // didn't require extending the file.  We know that the file doesn't
-            // need to be extended, so skip the extra work by not providing the
-            // size.
-            PRFileMap* map = PR_CreateFileMap(fileHandle, 0, PR_PROT_READONLY);
-            if (!map) {
-                NS_ERROR("Failed to create file map");
-                return NS_ERROR_FAILURE;
-            }
-
-            // Make sure the file map is closed, no matter how we return.
-            FileMapAutoCloser mapCloser(map);
-
-            uint32_t fileSize32 = fileSize;
-
-            char* buf = static_cast<char*>(PR_MemMap(map, 0, fileSize32));
-            if (!buf) {
-                NS_WARNING("Failed to map file");
-                return NS_ERROR_FAILURE;
-            }
-
-            Compile(cx, options, buf, fileSize32, &script);
-
-            PR_MemUnmap(buf, fileSize32);
+            auto buf = map.get<char>();
+            Compile(cx, options, buf.get(), map.size(), &script);
         } else {
             rv = aInfo.EnsureScriptChannel();
             NS_ENSURE_SUCCESS(rv, rv);
             nsCOMPtr<nsIInputStream> scriptStream;
             rv = NS_MaybeOpenChannelUsingOpen2(aInfo.ScriptChannel(),
                    getter_AddRefs(scriptStream));
             NS_ENSURE_SUCCESS(rv, rv);