nsXULPrototypeDocument* nsXULPrototypeCache::GetPrototype(nsIURI* aURI) { nsXULPrototypeDocument* protoDoc = mPrototypeTable.GetWeak(aURI); if (!protoDoc) { // No prototype in XUL memory cache. Spin up FastLoad Service and // look in FastLoad file. nsresult rv = StartFastLoad(aURI); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIObjectInputStream> objectInput; gFastLoadService->GetInputStream(getter_AddRefs(objectInput)); rv = StartFastLoadingURI(aURI, nsIFastLoadService::NS_FASTLOAD_READ); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIURI> oldURI; gFastLoadService->SelectMuxedDocument(aURI, getter_AddRefs(oldURI)); // Create a new prototype document. nsRefPtr<nsXULPrototypeDocument> newProto; rv = NS_NewXULPrototypeDocument(getter_AddRefs(newProto)); if (NS_FAILED(rv)) return nsnull; rv = newProto->Read(objectInput); if (NS_SUCCEEDED(rv)) { rv = PutPrototype(newProto); if (NS_FAILED(rv)) newProto = nsnull; gFastLoadService->EndMuxedDocument(aURI); } else { newProto = nsnull; } RemoveFromFastLoadSet(aURI); protoDoc = newProto; } } } return protoDoc; }
nsresult mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponent, JSObject **aGlobal, char **aLocation) { nsresult rv; JSPrincipals* jsPrincipals = nsnull; JSCLContextHelper cx(mContext); #ifndef XPCONNECT_STANDALONE rv = mSystemPrincipal->GetJSPrincipals(cx, &jsPrincipals); NS_ENSURE_SUCCESS(rv, rv); JSPrincipalsHolder princHolder(mContext, jsPrincipals); #endif nsCOMPtr<nsIXPCScriptable> backstagePass; rv = mRuntimeService->GetBackstagePass(getter_AddRefs(backstagePass)); NS_ENSURE_SUCCESS(rv, rv); JSCLAutoErrorReporterSetter aers(cx, mozJSLoaderErrorReporter); nsCOMPtr<nsIXPConnect> xpc = do_GetService(kXPConnectServiceContractID, &rv); NS_ENSURE_SUCCESS(rv, rv); // Make sure InitClassesWithNewWrappedGlobal() installs the // backstage pass as the global in our compilation context. JS_SetGlobalObject(cx, nsnull); nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass, NS_GET_IID(nsISupports), nsIXPConnect:: FLAG_SYSTEM_GLOBAL_OBJECT, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); JSObject *global; rv = holder->GetJSObject(&global); NS_ENSURE_SUCCESS(rv, rv); if (!JS_DefineFunctions(cx, global, gGlobalFun)) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIXPConnectJSObjectHolder> locationHolder; rv = xpc->WrapNative(cx, global, aComponent, NS_GET_IID(nsILocalFile), getter_AddRefs(locationHolder)); NS_ENSURE_SUCCESS(rv, rv); JSObject *locationObj; rv = locationHolder->GetJSObject(&locationObj); NS_ENSURE_SUCCESS(rv, rv); if (!JS_DefineProperty(cx, global, "__LOCATION__", OBJECT_TO_JSVAL(locationObj), nsnull, nsnull, 0)) { return NS_ERROR_FAILURE; } nsCAutoString nativePath; // Quick hack to unbust XPCONNECT_STANDALONE. // This leaves the jsdebugger with a non-URL pathname in the // XPCONNECT_STANDALONE case - but at least it builds and runs otherwise. // See: http://bugzilla.mozilla.org/show_bug.cgi?id=121438 #ifdef XPCONNECT_STANDALONE localFile->GetNativePath(nativePath); #else NS_GetURLSpecFromFile(aComponent, nativePath); #endif // Before compiling the script, first check to see if we have it in // the fastload file. Note: as a rule, fastload errors are not fatal // to loading the script, since we can always slow-load. nsCOMPtr<nsIFastLoadService> flSvc = do_GetFastLoadService(&rv); // Save the old state and restore it upon return FastLoadStateHolder flState(flSvc); PRBool fastLoading = PR_FALSE; if (NS_SUCCEEDED(rv)) { rv = StartFastLoad(flSvc); if (NS_SUCCEEDED(rv)) { fastLoading = PR_TRUE; } } nsCOMPtr<nsIURI> uri; rv = NS_NewURI(getter_AddRefs(uri), nativePath); NS_ENSURE_SUCCESS(rv, rv); JSScript *script = nsnull; if (fastLoading) { rv = ReadScript(flSvc, nativePath.get(), uri, cx, &script); if (NS_SUCCEEDED(rv)) { LOG(("Successfully loaded %s from fastload\n", nativePath.get())); fastLoading = PR_FALSE; // no need to write out the script } else if (rv == NS_ERROR_NOT_AVAILABLE) { // This is ok, it just means the script is not yet in the // fastload file. rv = NS_OK; } else { LOG(("Failed to deserialize %s\n", nativePath.get())); // Remove the fastload file, it may be corrupted. LOG(("Invalid fastload file detected, removing it\n")); nsCOMPtr<nsIObjectOutputStream> objectOutput; flSvc->GetOutputStream(getter_AddRefs(objectOutput)); if (objectOutput) { flSvc->SetOutputStream(nsnull); objectOutput->Close(); } nsCOMPtr<nsIObjectInputStream> objectInput; flSvc->GetInputStream(getter_AddRefs(objectInput)); if (objectInput) { flSvc->SetInputStream(nsnull); objectInput->Close(); } if (mFastLoadFile) { mFastLoadFile->Remove(PR_FALSE); } fastLoading = PR_FALSE; } } if (!script || NS_FAILED(rv)) { // The script wasn't in the fastload cache, so compile it now. LOG(("Slow loading %s\n", nativePath.get())); #ifdef HAVE_PR_MEMMAP PRInt64 fileSize; rv = aComponent->GetFileSize(&fileSize); if (NS_FAILED(rv)) return rv; PRInt64 maxSize; LL_UI2L(maxSize, PR_UINT32_MAX); if (LL_CMP(fileSize, >, maxSize)) { NS_ERROR("file too large"); return NS_ERROR_FAILURE; } PRFileDesc *fileHandle; rv = aComponent->OpenNSPRFileDesc(PR_RDONLY, 0, &fileHandle); NS_ENSURE_SUCCESS(rv, rv); // Make sure the file is closed, no matter how we return. FileAutoCloser fileCloser(fileHandle); PRFileMap *map = PR_CreateFileMap(fileHandle, fileSize, 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); PRUint32 fileSize32; LL_L2UI(fileSize32, fileSize); char *buf = static_cast<char*>(PR_MemMap(map, 0, fileSize32)); if (!buf) { NS_WARNING("Failed to map file"); return NS_ERROR_FAILURE; } script = JS_CompileScriptForPrincipals(cx, global, jsPrincipals, buf, fileSize32, nativePath.get(), 1); PR_MemUnmap(buf, fileSize32); #else /* HAVE_PR_MEMMAP */ /** * No memmap implementation, so fall back to using * JS_CompileFileHandleForPrincipals(). */ FILE *fileHandle; rv = aComponent->OpenANSIFileDesc("r", &fileHandle); NS_ENSURE_SUCCESS(rv, rv); script = JS_CompileFileHandleForPrincipals(cx, global, nativePath.get(), fileHandle, jsPrincipals); /* JS will close the filehandle after compilation is complete. */ #endif /* HAVE_PR_MEMMAP */ }