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
--- 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);