зеркало из https://github.com/mozilla/gecko-dev.git
Bug 316416 - Convert nsIComponentLoader into nsIModuleLoader, xpcom bits r=darin xpconnect bits r=shaver; and bug 318625 - Make a version of nsTArray.AppendElement that doesn't copy-construct, r=darin
This commit is contained in:
Родитель
568b305cac
Коммит
28e3019754
|
@ -48,10 +48,9 @@
|
|||
#include "prlog.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsIComponentLoader.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIComponentManagerObsolete.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIModule.h"
|
||||
|
@ -63,7 +62,6 @@
|
|||
#include "nsIXPConnect.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
#include "nsString.h"
|
||||
|
@ -72,7 +70,6 @@
|
|||
#include "nsIURI.h"
|
||||
#include "nsNetUtil.h"
|
||||
#endif
|
||||
#include "nsIComponentLoaderManager.h"
|
||||
#include "jsxdrapi.h"
|
||||
#include "nsIFastLoadFileControl.h"
|
||||
// For reporting errors with the console service
|
||||
|
@ -377,97 +374,36 @@ WriteScriptToStream(JSContext *cx, JSScript *script,
|
|||
mozJSComponentLoader::mozJSComponentLoader()
|
||||
: mRuntime(nsnull),
|
||||
mContext(nsnull),
|
||||
mModules(nsnull),
|
||||
mGlobals(nsnull),
|
||||
mInitialized(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(!sSelf, "mozJSComponentLoader should be a singleton");
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (!gJSCLLog) {
|
||||
gJSCLLog = PR_NewLogModule("JSComponentLoader");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static PRIntn PR_CALLBACK
|
||||
UnrootGlobals(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
JSContext *cx = (JSContext *)arg;
|
||||
JSObject *global = (JSObject *)he->value;
|
||||
JS_ClearScope(cx, global);
|
||||
JS_RemoveRoot(cx, &he->value);
|
||||
nsCRT::free((char *)he->key);
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
static PRIntn PR_CALLBACK
|
||||
UnloadAndReleaseModules(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
nsIModule *module = NS_STATIC_CAST(nsIModule *, he->value);
|
||||
nsIComponentManager *mgr = NS_STATIC_CAST(nsIComponentManager *, arg);
|
||||
PRBool canUnload;
|
||||
nsresult rv = module->CanUnload(mgr, &canUnload);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "module CanUnload failed");
|
||||
if (NS_SUCCEEDED(rv) && canUnload) {
|
||||
NS_RELEASE(module);
|
||||
/* XXX need to unroot the global for the module as well */
|
||||
nsCRT::free((char *)he->key);
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
sSelf = this;
|
||||
}
|
||||
|
||||
mozJSComponentLoader::~mozJSComponentLoader()
|
||||
{
|
||||
if (mInitialized) {
|
||||
NS_ERROR("'xpcom-shutdown-loaders' was not fired before cleaning up mozJSComponentLoader");
|
||||
UnloadModules();
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mFastLoadTimer,
|
||||
"Fastload file should have been closed via xpcom-shutdown");
|
||||
|
||||
sSelf = nsnull;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(mozJSComponentLoader, nsIComponentLoader, nsIObserver)
|
||||
mozJSComponentLoader*
|
||||
mozJSComponentLoader::sSelf;
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozJSComponentLoader::GetFactory(const nsIID &aCID,
|
||||
const char *aLocation,
|
||||
const char *aType,
|
||||
nsIFactory **_retval)
|
||||
{
|
||||
if (!_retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
#ifdef DEBUG_shaver_off
|
||||
char *cidString = aCID.ToString();
|
||||
fprintf(stderr, "mJCL::GetFactory(%s,%s,%s)\n", cidString, aLocation, aType);
|
||||
delete [] cidString;
|
||||
#endif
|
||||
|
||||
nsresult rv;
|
||||
nsIModule *module = ModuleForLocation(aLocation, 0, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
#ifdef DEBUG_shaver_off
|
||||
fprintf(stderr, "ERROR: couldn't get module for %s\n", aLocation);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = module->GetClassObject(mCompMgr, aCID, NS_GET_IID(nsIFactory),
|
||||
(void **)_retval);
|
||||
#ifdef DEBUG_shaver_off
|
||||
fprintf(stderr, "GetClassObject %s\n", NS_FAILED(rv) ? "FAILED" : "ok");
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozJSComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg)
|
||||
{
|
||||
mCompMgr = aCompMgr;
|
||||
|
||||
nsresult rv;
|
||||
mLoaderManager = do_QueryInterface(mCompMgr, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMPL_ISUPPORTS2(mozJSComponentLoader, nsIModuleLoader, nsIObserver)
|
||||
|
||||
nsresult
|
||||
mozJSComponentLoader::ReallyInit()
|
||||
|
@ -504,14 +440,7 @@ mozJSComponentLoader::ReallyInit()
|
|||
return NS_ERROR_FAILURE;
|
||||
#endif
|
||||
|
||||
mModules = PL_NewHashTable(16, PL_HashString, PL_CompareStrings,
|
||||
PL_CompareValues, 0, 0);
|
||||
if (!mModules)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mGlobals = PL_NewHashTable(16, PL_HashString, PL_CompareStrings,
|
||||
PL_CompareValues, 0, 0);
|
||||
if (!mGlobals)
|
||||
if (!mModules.Init(32))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Set up our fastload file
|
||||
|
@ -532,6 +461,9 @@ mozJSComponentLoader::ReallyInit()
|
|||
rv = obsSvc->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = obsSvc->AddObserver(this, "xpcom-shutdown-loaders", PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef DEBUG_shaver_off
|
||||
fprintf(stderr, "mJCL: ReallyInit success!\n");
|
||||
#endif
|
||||
|
@ -541,401 +473,62 @@ mozJSComponentLoader::ReallyInit()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozJSComponentLoader::AutoRegisterComponents(PRInt32 when,
|
||||
nsIFile *aDirectory)
|
||||
{
|
||||
return RegisterComponentsInDir(when, aDirectory);
|
||||
}
|
||||
|
||||
nsresult
|
||||
mozJSComponentLoader::RegisterComponentsInDir(PRInt32 when, nsIFile *dir)
|
||||
mozJSComponentLoader::LoadModule(nsILocalFile* aComponentFile,
|
||||
nsIModule* *aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool isDir;
|
||||
|
||||
if (NS_FAILED(rv = dir->IsDirectory(&isDir)))
|
||||
return rv;
|
||||
|
||||
if (!isDir)
|
||||
|
||||
nsCAutoString leafName;
|
||||
aComponentFile->GetNativeLeafName(leafName);
|
||||
if (!StringTail(leafName, 3).LowerCaseEqualsLiteral(".js"))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
// Create a directory iterator
|
||||
nsCOMPtr<nsISimpleEnumerator> dirIterator;
|
||||
rv = dir->GetDirectoryEntries(getter_AddRefs(dirIterator));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// whip through the directory to register every file
|
||||
nsIFile *dirEntry = NULL;
|
||||
PRBool more = PR_FALSE;
|
||||
|
||||
rv = dirIterator->HasMoreElements(&more);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
while (more == PR_TRUE)
|
||||
{
|
||||
rv = dirIterator->GetNext((nsISupports**)&dirEntry);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = dirEntry->IsDirectory(&isDir);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
if (isDir == PR_TRUE)
|
||||
{
|
||||
// This is a directory. Grovel for components into the directory.
|
||||
rv = RegisterComponentsInDir(when, dirEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRBool registered;
|
||||
// This is a file. Try to register it.
|
||||
rv = AutoRegisterComponent(when, dirEntry, ®istered);
|
||||
}
|
||||
}
|
||||
NS_RELEASE(dirEntry);
|
||||
}
|
||||
rv = dirIterator->HasMoreElements(&more);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
mozJSComponentLoader::SetRegistryInfo(const char *registryLocation,
|
||||
nsIFile *component)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!mLoaderManager)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRInt64 modDate;
|
||||
rv = component->GetLastModifiedTime(&modDate);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
#ifdef DEBUG_shaver_off
|
||||
fprintf(stderr, "SetRegistryInfo(%s) => (%d,%d)\n", registryLocation,
|
||||
modDate, fileSize);
|
||||
#endif
|
||||
return mLoaderManager->SaveFileInfo(component, registryLocation, modDate);
|
||||
}
|
||||
|
||||
nsresult
|
||||
mozJSComponentLoader::RemoveRegistryInfo(nsIFile *component, const char *registryLocation)
|
||||
{
|
||||
if (!mLoaderManager)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return mLoaderManager->RemoveFileInfo(component, registryLocation);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
mozJSComponentLoader::HasChanged(const char *registryLocation,
|
||||
nsIFile *component)
|
||||
{
|
||||
if (!mLoaderManager)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRInt64 lastTime;
|
||||
component->GetLastModifiedTime(&lastTime);
|
||||
|
||||
PRBool hasChanged = PR_TRUE;
|
||||
mLoaderManager->HasFileChanged(component, registryLocation, lastTime, &hasChanged);
|
||||
return hasChanged;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozJSComponentLoader::AutoRegisterComponent(PRInt32 when,
|
||||
nsIFile *component,
|
||||
PRBool *registered)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!registered)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
const char jsExtension[] = ".js";
|
||||
int jsExtensionLen = 3;
|
||||
nsCAutoString leafName;
|
||||
|
||||
*registered = PR_FALSE;
|
||||
|
||||
/* we only do files */
|
||||
PRBool isFile = PR_FALSE;
|
||||
if (NS_FAILED(rv = component->IsFile(&isFile)) || !isFile)
|
||||
return rv;
|
||||
|
||||
if (NS_FAILED(rv = component->GetNativeLeafName(leafName)))
|
||||
return rv;
|
||||
int len = leafName.Length();
|
||||
|
||||
/* if it's not *.js, return now */
|
||||
if (len < jsExtensionLen || // too short
|
||||
PL_strcasecmp(leafName.get() + len - jsExtensionLen, jsExtension))
|
||||
return NS_OK;
|
||||
|
||||
#ifdef DEBUG_shaver_off
|
||||
fprintf(stderr, "mJCL: registering JS component %s\n",
|
||||
leafName.get());
|
||||
#endif
|
||||
|
||||
rv = AttemptRegistration(component, PR_FALSE);
|
||||
#ifdef DEBUG_shaver_off
|
||||
if (NS_SUCCEEDED(rv))
|
||||
fprintf(stderr, "registered module %s\n", leafName.get());
|
||||
else if (rv == NS_ERROR_FACTORY_REGISTER_AGAIN)
|
||||
fprintf(stderr, "deferred module %s\n", leafName.get());
|
||||
else
|
||||
fprintf(stderr, "failed to register %s\n", leafName.get());
|
||||
#endif
|
||||
*registered = (PRBool) NS_SUCCEEDED(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozJSComponentLoader::AutoUnregisterComponent(PRInt32 when,
|
||||
nsIFile *component,
|
||||
PRBool *unregistered)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!unregistered)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
const char jsExtension[] = ".js";
|
||||
int jsExtensionLen = 3;
|
||||
nsCAutoString leafName;
|
||||
|
||||
*unregistered = PR_FALSE;
|
||||
|
||||
/* we only do files */
|
||||
PRBool isFile = PR_FALSE;
|
||||
if (NS_FAILED(rv = component->IsFile(&isFile)) || !isFile)
|
||||
return rv;
|
||||
|
||||
if (NS_FAILED(rv = component->GetNativeLeafName(leafName)))
|
||||
return rv;
|
||||
int len = leafName.Length();
|
||||
|
||||
/* if it's not *.js, return now */
|
||||
if (len < jsExtensionLen || // too short
|
||||
PL_strcasecmp(leafName.get() + len - jsExtensionLen, jsExtension))
|
||||
return NS_OK;
|
||||
|
||||
rv = UnregisterComponent(component);
|
||||
#ifdef DEBUG_dp
|
||||
if (NS_SUCCEEDED(rv))
|
||||
fprintf(stderr, "unregistered module %s\n", leafName.get());
|
||||
else
|
||||
fprintf(stderr, "failed to unregister %s\n", leafName.get());
|
||||
#endif
|
||||
*unregistered = (PRBool) NS_SUCCEEDED(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
mozJSComponentLoader::AttemptRegistration(nsIFile *component,
|
||||
PRBool deferred)
|
||||
{
|
||||
nsXPIDLCString registryLocation;
|
||||
nsresult rv;
|
||||
|
||||
// what I want to do here is QI for a Component Registration Manager. Since this
|
||||
// has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
|
||||
nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
|
||||
if (obsoleteManager)
|
||||
rv = obsoleteManager->RegistryLocationForSpec(component,
|
||||
getter_Copies(registryLocation));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
/* no need to check registry data on deferred reg */
|
||||
if (!deferred && !HasChanged(registryLocation, component))
|
||||
return NS_OK;
|
||||
|
||||
nsIModule *module = ModuleForLocation(registryLocation, component, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
SetRegistryInfo(registryLocation, component);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Notify observers, if any, of autoregistration work
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService(kObserverServiceContractID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIServiceManager> mgr;
|
||||
rv = NS_GetServiceManager(getter_AddRefs(mgr));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// this string can't come from a string bundle, because we
|
||||
// don't have string bundles yet.
|
||||
NS_ConvertASCIItoUCS2 fileName("(no name)");
|
||||
|
||||
// get the file name
|
||||
if (component) {
|
||||
component->GetLeafName(fileName);
|
||||
}
|
||||
|
||||
// this string can't come from a string bundle, because we
|
||||
// don't have string bundles yet.
|
||||
const nsPromiseFlatString &msg =
|
||||
PromiseFlatString(NS_LITERAL_STRING("Registering JS component ") +
|
||||
fileName);
|
||||
|
||||
observerService->NotifyObservers(mgr,
|
||||
NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
|
||||
msg.get());
|
||||
|
||||
rv = module->RegisterSelf(mCompMgr, component, registryLocation,
|
||||
MOZJSCOMPONENTLOADER_TYPE_NAME);
|
||||
if (rv == NS_ERROR_FACTORY_REGISTER_AGAIN) {
|
||||
if (!deferred) {
|
||||
mDeferredComponents.AppendElement(component);
|
||||
}
|
||||
/*
|
||||
* we don't enter in the registry because we may want to
|
||||
* try again on a later autoreg, in case a dependency has
|
||||
* become available.
|
||||
*/
|
||||
} else {
|
||||
SetRegistryInfo(registryLocation, component);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
mozJSComponentLoader::UnregisterComponent(nsIFile *component)
|
||||
{
|
||||
nsXPIDLCString registryLocation;
|
||||
nsresult rv;
|
||||
|
||||
// what I want to do here is QI for a Component Registration Manager. Since this
|
||||
// has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
|
||||
nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
|
||||
if (obsoleteManager)
|
||||
rv = obsoleteManager->RegistryLocationForSpec(component,
|
||||
getter_Copies(registryLocation));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsIModule *module = ModuleForLocation(registryLocation, component, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Notify observers, if any, of autoregistration work
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService(kObserverServiceContractID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIServiceManager> mgr;
|
||||
rv = NS_GetServiceManager(getter_AddRefs(mgr));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
const nsAFlatString &msg = NS_LITERAL_STRING("Unregistering JS component");
|
||||
observerService->NotifyObservers(mgr,
|
||||
NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
|
||||
msg.get());
|
||||
|
||||
rv = module->UnregisterSelf(mCompMgr, component, registryLocation);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Remove any autoreg specific info. Ignore error.
|
||||
RemoveRegistryInfo(component, registryLocation);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
mozJSComponentLoader::RegisterDeferredComponents(PRInt32 aWhen,
|
||||
PRBool *aRegistered)
|
||||
{
|
||||
nsresult rv;
|
||||
*aRegistered = PR_FALSE;
|
||||
|
||||
PRUint32 count;
|
||||
rv = mDeferredComponents.Count(&count);
|
||||
#ifdef DEBUG_shaver_off
|
||||
fprintf(stderr, "mJCL: registering deferred (%d)\n", count);
|
||||
#endif
|
||||
if (NS_FAILED(rv) || !count)
|
||||
return NS_OK;
|
||||
|
||||
for (PRUint32 i = 0; i < count; i++) {
|
||||
nsCOMPtr<nsIFile> component;
|
||||
rv = mDeferredComponents.QueryElementAt(i, NS_GET_IID(nsIFile), getter_AddRefs(component));
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
rv = AttemptRegistration(component, PR_TRUE /* deferred */);
|
||||
if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
|
||||
if (NS_SUCCEEDED(rv))
|
||||
*aRegistered = PR_TRUE;
|
||||
mDeferredComponents.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_shaver_off
|
||||
rv = mDeferredComponents.Count(&count);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (*aRegistered)
|
||||
fprintf(stderr, "mJCL: registered deferred, %d left\n",
|
||||
count);
|
||||
else
|
||||
fprintf(stderr, "mJCL: didn't register any components, %d left\n",
|
||||
count);
|
||||
}
|
||||
#endif
|
||||
/* are there any fatal errors? */
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsIModule*
|
||||
mozJSComponentLoader::ModuleForLocation(const char *registryLocation,
|
||||
nsIFile *component, nsresult *status)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!mInitialized) {
|
||||
rv = ReallyInit();
|
||||
if (NS_FAILED(rv)) {
|
||||
*status = rv;
|
||||
return nsnull;
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
PLHashNumber hash = PL_HashString(registryLocation);
|
||||
PLHashEntry **hep = PL_HashTableRawLookup(mModules, hash,
|
||||
registryLocation);
|
||||
PLHashEntry *he = *hep;
|
||||
if (he) {
|
||||
*status = NS_OK;
|
||||
return NS_STATIC_CAST(nsIModule*, he->value);
|
||||
nsCOMPtr<nsIHashable> lfhash(do_QueryInterface(aComponentFile));
|
||||
if (!lfhash) {
|
||||
NS_ERROR("nsLocalFile not implementing nsIHashable");
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
JSObject *global;
|
||||
rv = GlobalForLocation(registryLocation, component, &global);
|
||||
ModuleEntry* mod;
|
||||
if (mModules.Get(lfhash, &mod)) {
|
||||
NS_ASSERTION(mod->module, "Bad hashtable data!");
|
||||
NS_ADDREF(*aResult = mod->module);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoPtr<ModuleEntry> entry(new ModuleEntry);
|
||||
if (!entry)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
rv = GlobalForLocation(aComponentFile, &entry->global, &entry->location);
|
||||
if (NS_FAILED(rv)) {
|
||||
#ifdef DEBUG_shaver
|
||||
fprintf(stderr, "GlobalForLocation failed!\n");
|
||||
#endif
|
||||
*status = rv;
|
||||
return nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXPConnect> xpc = do_GetService(kXPConnectServiceContractID,
|
||||
&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
*status = rv;
|
||||
return nsnull;
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIComponentManager> cm;
|
||||
rv = NS_GetComponentManager(getter_AddRefs(cm));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
JSCLContextHelper cx(mContext);
|
||||
|
||||
JSObject* cm_jsobj;
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> cm_holder;
|
||||
rv = xpc->WrapNative(cx, global, mCompMgr,
|
||||
rv = xpc->WrapNative(cx, entry->global, cm,
|
||||
NS_GET_IID(nsIComponentManager),
|
||||
getter_AddRefs(cm_holder));
|
||||
|
||||
|
@ -944,8 +537,7 @@ mozJSComponentLoader::ModuleForLocation(const char *registryLocation,
|
|||
fprintf(stderr, "WrapNative(%p,%p,nsIComponentManager) failed: %x\n",
|
||||
(void *)(JSContext*)cx, (void *)mCompMgr, rv);
|
||||
#endif
|
||||
*status = rv;
|
||||
return nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = cm_holder->GetJSObject(&cm_jsobj);
|
||||
|
@ -953,32 +545,47 @@ mozJSComponentLoader::ModuleForLocation(const char *registryLocation,
|
|||
#ifdef DEBUG_shaver
|
||||
fprintf(stderr, "GetJSObject of ComponentManager failed\n");
|
||||
#endif
|
||||
*status = rv;
|
||||
return nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
JSObject* file_jsobj;
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> file_holder;
|
||||
rv = xpc->WrapNative(cx, entry->global, aComponentFile,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(file_holder));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = cm_holder->GetJSObject(&file_jsobj);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
JSCLAutoErrorReporterSetter aers(cx, Reporter);
|
||||
|
||||
jsval argv[2], retval, NSGetModule_val;
|
||||
|
||||
if (!JS_GetProperty(cx, global, "NSGetModule", &NSGetModule_val) ||
|
||||
if (!JS_GetProperty(cx, entry->global, "NSGetModule", &NSGetModule_val) ||
|
||||
JSVAL_IS_VOID(NSGetModule_val)) {
|
||||
*status = NS_ERROR_FAILURE;
|
||||
return nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (JS_TypeOfValue(cx, NSGetModule_val) != JSTYPE_FUNCTION) {
|
||||
nsCAutoString path;
|
||||
aComponentFile->GetNativePath(path);
|
||||
|
||||
JS_ReportError(cx, "%s has NSGetModule property that is not a function",
|
||||
registryLocation);
|
||||
*status = NS_ERROR_FAILURE;
|
||||
return nsnull;
|
||||
path.get());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
argv[0] = OBJECT_TO_JSVAL(cm_jsobj);
|
||||
argv[1] = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, registryLocation));
|
||||
if (!JS_CallFunctionValue(cx, global, NSGetModule_val, 2, argv, &retval)) {
|
||||
*status = NS_ERROR_FAILURE;
|
||||
return nsnull;
|
||||
argv[1] = OBJECT_TO_JSVAL(file_jsobj);
|
||||
if (!JS_CallFunctionValue(cx, entry->global, NSGetModule_val,
|
||||
2, argv, &retval)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_shaver_off
|
||||
|
@ -990,31 +597,29 @@ mozJSComponentLoader::ModuleForLocation(const char *registryLocation,
|
|||
JSObject *jsModuleObj;
|
||||
if (!JS_ValueToObject(cx, retval, &jsModuleObj)) {
|
||||
/* XXX report error properly */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "mJCL: couldn't convert %s's nsIModule to obj\n",
|
||||
registryLocation);
|
||||
#endif
|
||||
*status = NS_ERROR_FAILURE;
|
||||
return nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsIModule *module;
|
||||
rv = xpc->WrapJS(cx, jsModuleObj, NS_GET_IID(nsIModule), (void**)&module);
|
||||
rv = xpc->WrapJS(cx, jsModuleObj,
|
||||
NS_GET_IID(nsIModule), getter_AddRefs(entry->module));
|
||||
if (NS_FAILED(rv)) {
|
||||
/* XXX report error properly */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "mJCL: couldn't get nsIModule from jsval\n");
|
||||
#endif
|
||||
*status = rv;
|
||||
return nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* we hand our reference to the hash table, it'll be released much later */
|
||||
he = PL_HashTableRawAdd(mModules, hep, hash,
|
||||
nsCRT::strdup(registryLocation), module);
|
||||
// Cache this module for later
|
||||
if (!mModules.Put(lfhash, entry))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*status = NS_OK;
|
||||
return module;
|
||||
NS_ADDREF(*aResult = entry->module);
|
||||
|
||||
// The hash owns the ModuleEntry now, forget about it
|
||||
entry.forget();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Some stack based classes for cleaning up on early return
|
||||
|
@ -1308,25 +913,11 @@ mozJSComponentLoader::WriteScript(nsIFastLoadService *flSvc, JSScript *script,
|
|||
}
|
||||
|
||||
nsresult
|
||||
mozJSComponentLoader::GlobalForLocation(const char *aLocation,
|
||||
nsIFile *aComponent,
|
||||
JSObject **aGlobal)
|
||||
mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponent,
|
||||
JSObject **aGlobal,
|
||||
char **aLocation)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!mInitialized) {
|
||||
rv = ReallyInit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
PLHashNumber hash = PL_HashString(aLocation);
|
||||
PLHashEntry **hep = PL_HashTableRawLookup(mGlobals, hash, aLocation);
|
||||
PLHashEntry *he = *hep;
|
||||
if (he) {
|
||||
*aGlobal = NS_STATIC_CAST(JSObject*, he->value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aGlobal = nsnull;
|
||||
|
||||
JSPrincipals* jsPrincipals = nsnull;
|
||||
JSCLContextHelper cx(mContext);
|
||||
|
@ -1368,24 +959,8 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> component = aComponent;
|
||||
if (!component) {
|
||||
// what I want to do here is QI for a Component Registration Manager. Since this
|
||||
// has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
|
||||
nsCOMPtr<nsIComponentManagerObsolete> mgr = do_QueryInterface(mCompMgr,
|
||||
&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mgr->SpecForRegistryLocation(aLocation,
|
||||
getter_AddRefs(component));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(component, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> locationHolder;
|
||||
rv = xpc->WrapNative(cx, global, localFile,
|
||||
rv = xpc->WrapNative(cx, global, aComponent,
|
||||
NS_GET_IID(nsILocalFile),
|
||||
getter_AddRefs(locationHolder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1407,7 +982,7 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
|
|||
#ifdef XPCONNECT_STANDALONE
|
||||
localFile->GetNativePath(nativePath);
|
||||
#else
|
||||
NS_GetURLSpecFromFile(localFile, nativePath);
|
||||
NS_GetURLSpecFromFile(aComponent, nativePath);
|
||||
#endif
|
||||
|
||||
// Before compiling the script, first check to see if we have it in
|
||||
|
@ -1472,7 +1047,7 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
|
|||
|
||||
#ifdef HAVE_PR_MEMMAP
|
||||
PRInt64 fileSize;
|
||||
localFile->GetFileSize(&fileSize);
|
||||
aComponent->GetFileSize(&fileSize);
|
||||
|
||||
PRInt64 maxSize;
|
||||
LL_UI2L(maxSize, PR_UINT32_MAX);
|
||||
|
@ -1482,7 +1057,7 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
|
|||
}
|
||||
|
||||
PRFileDesc *fileHandle;
|
||||
rv = localFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fileHandle);
|
||||
rv = aComponent->OpenNSPRFileDesc(PR_RDONLY, 0, &fileHandle);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Make sure the file is closed, no matter how we return.
|
||||
|
@ -1521,7 +1096,7 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
|
|||
*/
|
||||
|
||||
FILE *fileHandle;
|
||||
rv = localFile->OpenANSIFileDesc("r", &fileHandle);
|
||||
rv = aComponent->OpenANSIFileDesc("r", &fileHandle);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
script = JS_CompileFileHandleForPrincipals(cx, global,
|
||||
|
@ -1551,7 +1126,7 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
|
|||
|
||||
if (fastLoading) {
|
||||
// We successfully compiled the script, so cache it in fastload.
|
||||
rv = WriteScript(flSvc, script, component, nativePath.get(), uri, cx);
|
||||
rv = WriteScript(flSvc, script, aComponent, nativePath.get(), uri, cx);
|
||||
|
||||
// Don't treat failure to write as fatal, since we might be working
|
||||
// with a read-only fastload file.
|
||||
|
@ -1573,76 +1148,56 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aGlobal = global;
|
||||
|
||||
/* Freed when we remove from the table. */
|
||||
char *location = nsCRT::strdup(aLocation);
|
||||
NS_ENSURE_TRUE(location, NS_ERROR_OUT_OF_MEMORY);
|
||||
nsCAutoString path;
|
||||
aComponent->GetNativePath(path);
|
||||
*aLocation = ToNewCString(path);
|
||||
if (!*aLocation)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
he = PL_HashTableRawAdd(mGlobals, hep, hash, location, global);
|
||||
JS_AddNamedRoot(cx, &he->value, location);
|
||||
*aGlobal = global;
|
||||
JS_AddNamedRoot(cx, aGlobal, *aLocation);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozJSComponentLoader::OnRegister(const nsIID &aCID, const char *aType,
|
||||
const char *aClassName, const char *aContractID,
|
||||
const char *aLocation,
|
||||
PRBool aReplace, PRBool aPersist)
|
||||
|
||||
void
|
||||
mozJSComponentLoader::UnloadModules()
|
||||
{
|
||||
#ifdef DEBUG_shaver_off
|
||||
fprintf(stderr, "mJCL: registered %s/%s in %s\n", aClassName, aContractID,
|
||||
aLocation);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
mInitialized = PR_FALSE;
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozJSComponentLoader::UnloadAll(PRInt32 aWhen)
|
||||
{
|
||||
if (mInitialized) {
|
||||
mInitialized = PR_FALSE;
|
||||
mModules.Clear();
|
||||
|
||||
// stabilize the component manager, etc.
|
||||
nsCOMPtr<nsIComponentManager> kungFuDeathGrip = mCompMgr;
|
||||
// Destroying our context will force a GC.
|
||||
JS_DestroyContext(mContext);
|
||||
mContext = nsnull;
|
||||
|
||||
PL_HashTableEnumerateEntries(mModules,
|
||||
UnloadAndReleaseModules,
|
||||
mCompMgr);
|
||||
PL_HashTableDestroy(mModules);
|
||||
mModules = nsnull;
|
||||
|
||||
PL_HashTableEnumerateEntries(mGlobals, UnrootGlobals, mContext);
|
||||
PL_HashTableDestroy(mGlobals);
|
||||
mGlobals = nsnull;
|
||||
|
||||
// Destroying our context will force a GC.
|
||||
JS_DestroyContext(mContext);
|
||||
mContext = nsnull;
|
||||
|
||||
mRuntimeService = nsnull;
|
||||
}
|
||||
mRuntimeService = nsnull;
|
||||
|
||||
#ifdef DEBUG_shaver_off
|
||||
fprintf(stderr, "mJCL: UnloadAll(%d)\n", aWhen);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozJSComponentLoader::Observe(nsISupports *subject, const char *topic,
|
||||
const PRUnichar *data)
|
||||
{
|
||||
NS_ASSERTION(!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID),
|
||||
"Unexpected observer topic");
|
||||
if (!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
if (mFastLoadTimer) {
|
||||
mFastLoadTimer->Cancel();
|
||||
}
|
||||
|
||||
if (mFastLoadTimer) {
|
||||
mFastLoadTimer->Cancel();
|
||||
JS_GC(mContext);
|
||||
|
||||
CloseFastLoad();
|
||||
}
|
||||
else if (!strcmp(topic, "xpcom-shutdown-loaders")) {
|
||||
UnloadModules();
|
||||
}
|
||||
else {
|
||||
NS_ERROR("Unexpected observer topic.");
|
||||
}
|
||||
|
||||
CloseFastLoad();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1663,7 +1218,3 @@ JSCLContextHelper::~JSCLContextHelper()
|
|||
if (mContextThread)
|
||||
JS_EndRequest(mContext);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/* XXX this should all be data-driven, via NS_IMPL_GETMODULE_WITH_CATEGORIES */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
@ -39,14 +39,12 @@
|
|||
|
||||
#include "plhash.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsIComponentLoader.h"
|
||||
#include "nsIComponentLoaderManager.h"
|
||||
#include "nsIModuleLoader.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIModule.h"
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIFastLoadService.h"
|
||||
|
@ -54,6 +52,7 @@
|
|||
#include "nsIObjectOutputStream.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#ifndef XPCONNECT_STANDALONE
|
||||
#include "nsIPrincipal.h"
|
||||
#endif
|
||||
|
@ -89,29 +88,26 @@ class nsXPCFastLoadIO : public nsIFastLoadFileIO
|
|||
};
|
||||
|
||||
|
||||
class mozJSComponentLoader : public nsIComponentLoader,
|
||||
class mozJSComponentLoader : public nsIModuleLoader,
|
||||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICOMPONENTLOADER
|
||||
NS_DECL_NSIMODULELOADER
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
mozJSComponentLoader();
|
||||
virtual ~mozJSComponentLoader();
|
||||
|
||||
protected:
|
||||
static mozJSComponentLoader* sSelf;
|
||||
|
||||
nsresult ReallyInit();
|
||||
nsresult AttemptRegistration(nsIFile *component, PRBool deferred);
|
||||
nsresult UnregisterComponent(nsIFile *component);
|
||||
nsresult RegisterComponentsInDir(PRInt32 when, nsIFile *dir);
|
||||
nsresult GlobalForLocation(const char *aLocation, nsIFile *aComponent,
|
||||
JSObject **aGlobal);
|
||||
nsIModule* ModuleForLocation(const char *aLocation, nsIFile *component,
|
||||
nsresult *status);
|
||||
PRBool HasChanged(const char *registryLocation, nsIFile *component);
|
||||
nsresult SetRegistryInfo(const char *registryLocation, nsIFile *component);
|
||||
nsresult RemoveRegistryInfo(nsIFile *component, const char *registryLocation);
|
||||
void UnloadModules();
|
||||
|
||||
nsresult GlobalForLocation(nsILocalFile *aComponent,
|
||||
JSObject **aGlobal,
|
||||
char **location);
|
||||
|
||||
nsresult StartFastLoad(nsIFastLoadService *flSvc);
|
||||
nsresult ReadScript(nsIFastLoadService *flSvc, const char *nativePath,
|
||||
|
@ -123,7 +119,6 @@ class mozJSComponentLoader : public nsIComponentLoader,
|
|||
void CloseFastLoad();
|
||||
|
||||
nsCOMPtr<nsIComponentManager> mCompMgr;
|
||||
nsCOMPtr<nsIComponentLoaderManager> mLoaderManager;
|
||||
nsCOMPtr<nsIJSRuntimeService> mRuntimeService;
|
||||
nsCOMPtr<nsIFile> mFastLoadFile;
|
||||
nsRefPtr<nsXPCFastLoadIO> mFastLoadIO;
|
||||
|
@ -135,9 +130,33 @@ class mozJSComponentLoader : public nsIComponentLoader,
|
|||
#endif
|
||||
JSRuntime *mRuntime;
|
||||
JSContext *mContext;
|
||||
PLHashTable *mModules;
|
||||
PLHashTable *mGlobals;
|
||||
|
||||
class ModuleEntry
|
||||
{
|
||||
public:
|
||||
ModuleEntry() {
|
||||
global = nsnull;
|
||||
location = nsnull;
|
||||
}
|
||||
|
||||
~ModuleEntry() {
|
||||
module = nsnull;
|
||||
|
||||
if (global) {
|
||||
JS_ClearScope(sSelf->mContext, global);
|
||||
JS_RemoveRoot(sSelf->mContext, &global);
|
||||
}
|
||||
|
||||
if (location)
|
||||
NS_Free(location);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIModule> module;
|
||||
JSObject *global;
|
||||
char *location;
|
||||
};
|
||||
|
||||
nsClassHashtable<nsHashableHashKey, ModuleEntry> mModules;
|
||||
|
||||
PRBool mInitialized;
|
||||
nsSupportsArray mDeferredComponents;
|
||||
};
|
||||
|
|
|
@ -64,7 +64,7 @@ RegisterJSLoader(nsIComponentManager *aCompMgr, nsIFile *aPath,
|
|||
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsXPIDLCString previous;
|
||||
return catman->AddCategoryEntry("component-loader",
|
||||
return catman->AddCategoryEntry("module-loader",
|
||||
MOZJSCOMPONENTLOADER_TYPE_NAME,
|
||||
MOZJSCOMPONENTLOADER_CONTRACTID,
|
||||
PR_TRUE, PR_TRUE, getter_Copies(previous));
|
||||
|
@ -80,14 +80,14 @@ UnregisterJSLoader(nsIComponentManager *aCompMgr, nsIFile *aPath,
|
|||
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsXPIDLCString jsLoader;
|
||||
rv = catman->GetCategoryEntry("component-loader",
|
||||
rv = catman->GetCategoryEntry("module-loader",
|
||||
MOZJSCOMPONENTLOADER_TYPE_NAME,
|
||||
getter_Copies(jsLoader));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// only unregister if we're the current JS component loader
|
||||
if (!strcmp(jsLoader, MOZJSCOMPONENTLOADER_CONTRACTID)) {
|
||||
return catman->DeleteCategoryEntry("component-loader",
|
||||
return catman->DeleteCategoryEntry("module-loader",
|
||||
MOZJSCOMPONENTLOADER_TYPE_NAME,
|
||||
PR_TRUE);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
#include "nsISupportsUtils.h"
|
||||
#include "nsTraceRefcntImpl.h"
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386)
|
||||
#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64__))
|
||||
# define DebugBreak() { asm("int $3"); }
|
||||
#elif defined(__APPLE__) && defined(TARGET_CARBON)
|
||||
# include "MacTypes.h"
|
||||
|
|
|
@ -268,9 +268,4 @@ NS_GetFrozenFunctions(XPCOMFunctions *entryPoints, const char* libraryPath);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
NewStaticComponentLoader(nsStaticModuleInfo const *aStaticModules,
|
||||
PRUint32 aStaticModuleCount,
|
||||
nsIComponentLoader **retval);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -284,8 +284,8 @@ static PRBool CheckUpdateFile()
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Don't need to check whether compreg exists; if it doesn't
|
||||
// we won't even be here.
|
||||
if (NS_FAILED(compregFile->Exists(&exists)) || !exists)
|
||||
return PR_TRUE;
|
||||
|
||||
PRInt64 compregModTime, autoregModTime;
|
||||
compregFile->GetLastModifiedTime(&compregModTime);
|
||||
|
@ -619,98 +619,18 @@ NS_InitXPCOM3(nsIServiceManager* *result,
|
|||
NS_INIPARSERFACTORY_CONTRACTID,
|
||||
iniParserFactory);
|
||||
}
|
||||
rv = nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry();
|
||||
#ifdef DEBUG
|
||||
if (NS_FAILED(rv)) {
|
||||
printf("No Persistent Registry Found.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( NS_FAILED(rv) || CheckUpdateFile()) {
|
||||
// if we find no persistent registry, we will try to autoregister
|
||||
// the default components directory.
|
||||
nsComponentManagerImpl::gComponentManager->AutoRegister(nsnull);
|
||||
|
||||
// If the application is using a GRE, then,
|
||||
// auto register components in the GRE directory as well.
|
||||
//
|
||||
// The application indicates that it's using an GRE by
|
||||
// returning a valid nsIFile when queried (via appFileLocProvider)
|
||||
// for the NS_GRE_DIR atom as shown below
|
||||
//
|
||||
|
||||
if ( appFileLocationProvider ) {
|
||||
nsCOMPtr<nsIFile> greDir;
|
||||
PRBool persistent = PR_TRUE;
|
||||
|
||||
appFileLocationProvider->GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(greDir));
|
||||
|
||||
if (greDir) {
|
||||
#ifdef DEBUG_dougt
|
||||
printf("start - Registering GRE components\n");
|
||||
#endif
|
||||
rv = nsDirectoryService::gService->Get(NS_GRE_COMPONENT_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(greDir));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Could not get GRE components directory!");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If the GRE contains any loaders, we want to know about it so that we can cause another
|
||||
// autoregistration of the applications component directory.
|
||||
int loaderCount = nsComponentManagerImpl::gComponentManager->GetLoaderCount();
|
||||
rv = nsComponentManagerImpl::gComponentManager->AutoRegister(greDir);
|
||||
|
||||
if (loaderCount != nsComponentManagerImpl::gComponentManager->GetLoaderCount())
|
||||
nsComponentManagerImpl::gComponentManager->AutoRegisterNonNativeComponents(nsnull);
|
||||
|
||||
#ifdef DEBUG_dougt
|
||||
printf("end - Registering GRE components\n");
|
||||
#endif
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Could not AutoRegister GRE components");
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If additional component directories have been specified, then
|
||||
// register them as well.
|
||||
//
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> dirList;
|
||||
nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_DIR_LIST,
|
||||
NS_GET_IID(nsISimpleEnumerator),
|
||||
getter_AddRefs(dirList));
|
||||
if (dirList) {
|
||||
PRBool hasMore;
|
||||
while (NS_SUCCEEDED(dirList->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> elem;
|
||||
dirList->GetNext(getter_AddRefs(elem));
|
||||
if (elem) {
|
||||
nsCOMPtr<nsIFile> dir = do_QueryInterface(elem);
|
||||
if (dir)
|
||||
nsComponentManagerImpl::gComponentManager->AutoRegister(dir);
|
||||
|
||||
// XXX should we worry about new component loaders being
|
||||
// XXX defined by this process?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Make sure the compreg file's mod time is current.
|
||||
nsCOMPtr<nsIFile> compregFile;
|
||||
rv = nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(compregFile));
|
||||
compregFile->SetLastModifiedTime(PR_Now() / 1000);
|
||||
}
|
||||
|
||||
// Pay the cost at startup time of starting this singleton.
|
||||
(void) xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
|
||||
nsIInterfaceInfoManager* iim =
|
||||
xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
|
||||
|
||||
if (CheckUpdateFile() || NS_FAILED(
|
||||
nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry())) {
|
||||
// If the component registry is out of date, malformed, or incomplete,
|
||||
// autoregister the default component directories.
|
||||
(void) iim->AutoRegisterInterfaces();
|
||||
nsComponentManagerImpl::gComponentManager->AutoRegister(nsnull);
|
||||
}
|
||||
|
||||
// After autoreg, but before we actually instantiate any components,
|
||||
// add any services listed in the "xpcom-directory-providers" category
|
||||
|
@ -852,16 +772,16 @@ NS_ShutdownXPCOM(nsIServiceManager* servMgr)
|
|||
// here again:
|
||||
NS_IF_RELEASE(servMgr);
|
||||
|
||||
// Shutdown global servicemanager
|
||||
if (nsComponentManagerImpl::gComponentManager) {
|
||||
nsComponentManagerImpl::gComponentManager->FreeServices();
|
||||
}
|
||||
|
||||
if (currentQ) {
|
||||
currentQ->ProcessPendingEvents();
|
||||
currentQ = 0;
|
||||
}
|
||||
|
||||
// Shutdown global servicemanager
|
||||
if (nsComponentManagerImpl::gComponentManager) {
|
||||
nsComponentManagerImpl::gComponentManager->FreeServices();
|
||||
}
|
||||
|
||||
nsProxyObjectManager::Shutdown();
|
||||
|
||||
// Release the directory service
|
||||
|
|
|
@ -57,21 +57,17 @@ CPPSRCS = \
|
|||
nsNativeComponentLoader.cpp \
|
||||
nsStaticComponentLoader.cpp \
|
||||
nsServiceManagerObsolete.cpp \
|
||||
xcDll.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsCategoryManagerUtils.h \
|
||||
nsIServiceManagerObsolete.h \
|
||||
nsModule.h \
|
||||
nsNativeComponentLoader.h \
|
||||
nsObsoleteModuleLoading.h \
|
||||
xcDll.h \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIComponentLoader.idl \
|
||||
nsIComponentLoaderManager.idl \
|
||||
nsIModuleLoader.idl \
|
||||
nsIComponentManagerObsolete.idl \
|
||||
$(NULL)
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -40,15 +40,17 @@
|
|||
|
||||
#include "nsXPCOM.h"
|
||||
|
||||
#include "nsIComponentLoader.h"
|
||||
#include "xpcom-private.h"
|
||||
#include "nsNativeComponentLoader.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIComponentRegistrar.h"
|
||||
#include "nsIComponentManagerObsolete.h"
|
||||
#include "nsIComponentLoaderManager.h"
|
||||
#include "nsCategoryManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIModule.h"
|
||||
#include "nsIModuleLoader.h"
|
||||
#include "nsStaticComponentLoader.h"
|
||||
#include "nsNativeComponentLoader.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
@ -57,12 +59,13 @@
|
|||
#include "prmon.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIFile.h"
|
||||
#include "plarena.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsFactoryEntry;
|
||||
class nsDll;
|
||||
struct nsFactoryEntry;
|
||||
class nsIServiceManager;
|
||||
|
||||
#define NS_COMPONENTMANAGER_CID \
|
||||
|
@ -81,14 +84,12 @@ extern const char fileSizeValueName[];
|
|||
extern const char nativeComponentType[];
|
||||
extern const char staticComponentType[];
|
||||
|
||||
// Predefined loader types. Do not change the numbers.
|
||||
// NATIVE should be 0 as it is being used as the first array index.
|
||||
#define NS_COMPONENT_TYPE_NATIVE 0
|
||||
#define NS_COMPONENT_TYPE_FACTORY_ONLY -1
|
||||
// this define means that the factory entry only has a ContractID
|
||||
// to service mapping and has no cid mapping.
|
||||
#define NS_COMPONENT_TYPE_SERVICE_ONLY -2
|
||||
typedef int LoaderType;
|
||||
|
||||
// Predefined loader types.
|
||||
#define NS_LOADER_TYPE_NATIVE -1
|
||||
#define NS_LOADER_TYPE_STATIC -2
|
||||
#define NS_LOADER_TYPE_INVALID -3
|
||||
|
||||
#ifdef DEBUG
|
||||
#define XPCOM_CHECK_PENDING_CIDS
|
||||
|
@ -97,8 +98,22 @@ extern const char staticComponentType[];
|
|||
|
||||
// Array of Loaders and their type strings
|
||||
struct nsLoaderdata {
|
||||
nsIComponentLoader *loader;
|
||||
const char *type;
|
||||
nsCOMPtr<nsIModuleLoader> loader;
|
||||
nsCString type;
|
||||
};
|
||||
|
||||
// Deferred modules are kept as a nsTArray of this type. This is not a nested
|
||||
// class so that nsStaticComponentLoader.h can forward-declare it.
|
||||
struct DeferredModule
|
||||
{
|
||||
DeferredModule() :
|
||||
type(nsnull), modTime(0) { }
|
||||
|
||||
const char *type;
|
||||
nsCOMPtr<nsILocalFile> file;
|
||||
nsCString location;
|
||||
nsCOMPtr<nsIModule> module;
|
||||
PRInt64 modTime;
|
||||
};
|
||||
|
||||
class nsComponentManagerImpl
|
||||
|
@ -107,7 +122,6 @@ class nsComponentManagerImpl
|
|||
public nsIComponentRegistrar,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIComponentLoaderManager,
|
||||
public nsIServiceManagerObsolete,
|
||||
public nsIComponentManagerObsolete
|
||||
{
|
||||
|
@ -143,9 +157,13 @@ public:
|
|||
NS_IMETHOD CIDToContractID(const nsCID & aClass, char **_retval);
|
||||
NS_IMETHOD ContractIDToCID(const char *aContractID, nsCID * *_retval);
|
||||
|
||||
nsresult RegistryLocationForFile(nsIFile* aFile,
|
||||
nsCString& aResult);
|
||||
nsresult FileForRegistryLocation(const nsCString &aLocation,
|
||||
nsILocalFile **aSpec);
|
||||
|
||||
NS_DECL_NSISERVICEMANAGER
|
||||
NS_DECL_NSISERVICEMANAGEROBSOLETE
|
||||
NS_DECL_NSICOMPONENTLOADERMANAGER
|
||||
|
||||
// nsComponentManagerImpl methods:
|
||||
nsComponentManagerImpl();
|
||||
|
@ -153,6 +171,8 @@ public:
|
|||
static nsComponentManagerImpl* gComponentManager;
|
||||
nsresult Init(nsStaticModuleInfo const *aStaticModules,
|
||||
PRUint32 aStaticModuleCount);
|
||||
// NOTE: XPCOM initialization must call either ReadPersistentRegistry or
|
||||
// AutoRegister to fully initialize the nsComponentManagerImpl.
|
||||
|
||||
nsresult WritePersistentRegistry();
|
||||
nsresult ReadPersistentRegistry();
|
||||
|
@ -172,8 +192,18 @@ public:
|
|||
PRUint32 aRegistryNameLen,
|
||||
PRBool aReplace, PRBool aPersist,
|
||||
const char *aType);
|
||||
nsresult GetLoaderForType(int aType,
|
||||
nsIComponentLoader **aLoader);
|
||||
// Convert a loader type string into an index into the loader data
|
||||
// array. Empty loader types are converted to NATIVE. Returns
|
||||
// NS_LOADER_TYPE_INVALID if loader type cannot be determined.
|
||||
LoaderType GetLoaderType(const char *typeStr);
|
||||
LoaderType AddLoaderType(const char *typeStr);
|
||||
const char* StringForLoaderType(LoaderType aType) {
|
||||
return mLoaderData[aType].type.get();
|
||||
}
|
||||
nsIModuleLoader* LoaderForType(LoaderType aType);
|
||||
int GetLoaderCount() { return mLoaderData.Length(); }
|
||||
void GetAllLoaders();
|
||||
|
||||
nsresult FindFactory(const char *contractID, PRUint32 aContractIDLen, nsIFactory **aFactory) ;
|
||||
nsresult LoadFactory(nsFactoryEntry *aEntry, nsIFactory **aFactory);
|
||||
|
||||
|
@ -182,40 +212,31 @@ public:
|
|||
nsFactoryEntry *GetFactoryEntry(const nsCID &aClass);
|
||||
|
||||
nsresult SyncComponentsInDir(PRInt32 when, nsIFile *dirSpec);
|
||||
nsresult SelfRegisterDll(nsDll *dll);
|
||||
nsresult SelfUnregisterDll(nsDll *dll);
|
||||
nsresult HashContractID(const char *acontractID, PRUint32 aContractIDLen,
|
||||
nsFactoryEntry *fe_ptr);
|
||||
|
||||
void DeleteContractIDEntriesByCID(const nsCID* aClass, nsIFactory* factory);
|
||||
nsresult AutoRegisterImpl(nsIFile* inDirSpec,
|
||||
nsCOMArray<nsILocalFile> &aLeftovers,
|
||||
nsTArray<DeferredModule> &aDeferred);
|
||||
nsresult AutoRegisterDirectory(nsIFile* aComponentFile,
|
||||
nsCOMArray<nsILocalFile> &aLeftovers,
|
||||
nsTArray<DeferredModule> &aDeferred);
|
||||
nsresult AutoRegisterComponent(nsILocalFile* aComponentFile,
|
||||
nsTArray<DeferredModule> &aDeferred,
|
||||
LoaderType minLoader = NS_LOADER_TYPE_NATIVE);
|
||||
void LoadLeftoverComponents(nsCOMArray<nsILocalFile> &aLeftovers,
|
||||
nsTArray<DeferredModule> &aDeferred,
|
||||
LoaderType minLoader);
|
||||
|
||||
nsresult UnloadLibraries(nsIServiceManager *servmgr, PRInt32 when);
|
||||
|
||||
// Convert a loader type string into an index into the loader data
|
||||
// array. Empty loader types are converted to NATIVE. Returns -1 if
|
||||
// loader type cannot be determined.
|
||||
int GetLoaderType(const char *typeStr);
|
||||
|
||||
// Add a loader type if not already known. Out the typeIndex
|
||||
// if the loader type is either added or already there;
|
||||
// returns NS_OK or an error on failure.
|
||||
nsresult AddLoaderType(const char *typeStr, int *typeIndex);
|
||||
|
||||
int GetLoaderCount() { return mNLoaderData + 1; }
|
||||
|
||||
// registers only the files in spec's location by loaders other than the
|
||||
// native loader. This is an optimization method only.
|
||||
nsresult AutoRegisterNonNativeComponents(nsIFile* spec);
|
||||
|
||||
nsresult AutoRegisterImpl(PRInt32 when, nsIFile *inDirSpec, PRBool fileIsCompDir=PR_TRUE);
|
||||
nsresult RemoveEntries(nsIFile* file);
|
||||
void LoadDeferredModules(nsTArray<DeferredModule> &aDeferred);
|
||||
|
||||
PLDHashTable mFactories;
|
||||
PLDHashTable mContractIDs;
|
||||
PRMonitor* mMon;
|
||||
|
||||
nsNativeComponentLoader *mNativeComponentLoader;
|
||||
nsIComponentLoader *mStaticComponentLoader;
|
||||
nsNativeModuleLoader mNativeModuleLoader;
|
||||
nsStaticModuleLoader mStaticModuleLoader;
|
||||
nsCOMPtr<nsIFile> mComponentsDir;
|
||||
PRInt32 mComponentsOffset;
|
||||
|
||||
|
@ -230,12 +251,11 @@ public:
|
|||
#define NS_SHUTDOWN_COMPLETE 2
|
||||
PRUint32 mShuttingDown;
|
||||
|
||||
nsLoaderdata *mLoaderData;
|
||||
int mNLoaderData;
|
||||
int mMaxNLoaderData;
|
||||
nsTArray<nsLoaderdata> mLoaderData;
|
||||
|
||||
nsDataHashtable<nsHashableHashKey, PRInt64> mAutoRegEntries;
|
||||
|
||||
PRBool mRegistryDirty;
|
||||
nsHashtable mAutoRegEntries;
|
||||
nsCOMPtr<nsCategoryManager> mCategoryManager;
|
||||
|
||||
PLArenaPool mArena;
|
||||
|
@ -271,51 +291,35 @@ private:
|
|||
* These are strictly session specific and in memory only.
|
||||
*/
|
||||
|
||||
class nsFactoryEntry {
|
||||
public:
|
||||
nsFactoryEntry(const nsCID &aClass,
|
||||
const char *location, PRUint32 locationlen, int aType, class nsFactoryEntry* parent = nsnull);
|
||||
nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory, class nsFactoryEntry* parent = nsnull);
|
||||
~nsFactoryEntry();
|
||||
struct nsFactoryEntry {
|
||||
nsFactoryEntry(const nsCID &aClass,
|
||||
LoaderType aLoaderType,
|
||||
const char *aLocationKey,
|
||||
nsFactoryEntry *aParent = nsnull);
|
||||
|
||||
nsresult ReInit(const nsCID &aClass, const char *location, int aType);
|
||||
|
||||
nsresult GetFactory(nsIFactory **aFactory,
|
||||
nsComponentManagerImpl * mgr) {
|
||||
if (mFactory) {
|
||||
*aFactory = mFactory.get();
|
||||
NS_ADDREF(*aFactory);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mTypeIndex < 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIComponentLoader> loader;
|
||||
rv = mgr->GetLoaderForType(mTypeIndex, getter_AddRefs(loader));
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = loader->GetFactory(mCid, mLocation, mgr->mLoaderData[mTypeIndex].type, aFactory);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
NS_ASSERTION(*aFactory, "Loader says it succeeded; got null factory!");
|
||||
mFactory = do_QueryInterface(*aFactory);
|
||||
if (!mFactory)
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
return NS_OK;
|
||||
nsFactoryEntry(const nsCID &aClass,
|
||||
nsIFactory *aFactory,
|
||||
nsFactoryEntry *aParent = nsnull) :
|
||||
mCid(aClass),
|
||||
mLoaderType(NS_LOADER_TYPE_INVALID),
|
||||
mFactory(aFactory),
|
||||
mParent(aParent) {
|
||||
mLocationKey = nsnull;
|
||||
}
|
||||
|
||||
nsCID mCid;
|
||||
nsCOMPtr<nsIFactory> mFactory;
|
||||
// This is an index into the mLoaderData array that holds the type string and the loader
|
||||
int mTypeIndex;
|
||||
nsCOMPtr<nsISupports> mServiceObject;
|
||||
char* mLocation;
|
||||
class nsFactoryEntry* mParent;
|
||||
~nsFactoryEntry();
|
||||
|
||||
void ReInit(LoaderType aLoaderType,
|
||||
const char *aLocationKey);
|
||||
|
||||
nsresult GetFactory(nsIFactory **aFactory);
|
||||
|
||||
nsCID mCid;
|
||||
LoaderType mLoaderType;
|
||||
const char *mLocationKey;
|
||||
nsCOMPtr<nsIFactory> mFactory;
|
||||
nsCOMPtr<nsISupports> mServiceObject;
|
||||
nsFactoryEntry *mParent;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -330,29 +334,5 @@ struct nsContractIDTableEntry : public PLDHashEntryHdr {
|
|||
nsFactoryEntry *mFactoryEntry;
|
||||
};
|
||||
|
||||
|
||||
class AutoRegEntry
|
||||
{
|
||||
public:
|
||||
AutoRegEntry(const nsACString& name, PRInt64* modDate);
|
||||
~AutoRegEntry();
|
||||
|
||||
const nsDependentCString GetName()
|
||||
{ return nsDependentCString(mName, mNameLen); }
|
||||
PRInt64 GetDate() {return mModDate;}
|
||||
void SetDate(PRInt64 *date) { mModDate = *date;}
|
||||
PRBool Modified(PRInt64 *date);
|
||||
|
||||
// this is the optional field line in the compreg.dat.
|
||||
// it must not contain any comma's and it must be null terminated.
|
||||
char* GetOptionalData() {return mData;};
|
||||
void SetOptionalData(const char* data);
|
||||
|
||||
private:
|
||||
char* mName;
|
||||
PRUint32 mNameLen;
|
||||
char* mData;
|
||||
PRInt64 mModDate;
|
||||
};
|
||||
#endif // nsComponentManager_h__
|
||||
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIFactory.idl"
|
||||
#include "nsIFile.idl"
|
||||
#include "nsIComponentManager.idl"
|
||||
|
||||
[object, uuid(c073cfc0-567c-11d3-aec1-0000f8e25c06)]
|
||||
interface nsIComponentLoader : nsISupports {
|
||||
|
||||
/**
|
||||
* Get the factory for a given component.
|
||||
*/
|
||||
nsIFactory getFactory(in nsIIDRef aCID, in string aLocation,
|
||||
in string aType);
|
||||
|
||||
/**
|
||||
* Initialize the loader.
|
||||
*
|
||||
* We use nsISupports here because nsIRegistry isn't IDLized yet.
|
||||
*/
|
||||
void init(in nsIComponentManager aCompMgr, in nsISupports aRegistry);
|
||||
|
||||
/**
|
||||
* Called when a component of the appropriate type is registered,
|
||||
* to give the component loader an opportunity to do things like
|
||||
* annotate the registry and such.
|
||||
*/
|
||||
void onRegister(in nsIIDRef aCID, in string aType,
|
||||
in string aClassName, in string aContractID,
|
||||
in string aLocation, in boolean aReplace,
|
||||
in boolean aPersist);
|
||||
|
||||
/**
|
||||
* When is AutoRegistration occuring?
|
||||
*/
|
||||
const long Startup = 0;
|
||||
const long Component = 1;
|
||||
const long Timer = 2;
|
||||
|
||||
/**
|
||||
* AutoRegister components in the given directory.
|
||||
*/
|
||||
void autoRegisterComponents(in long aWhen, in nsIFile aDirectory);
|
||||
|
||||
/**
|
||||
* AutoRegister the given component.
|
||||
*
|
||||
* Returns true if the component was registered, false if it couldn't
|
||||
* attempt to register the component (wrong type) and ``throws'' an
|
||||
* NS_FAILED code if there was an error during registration.
|
||||
*/
|
||||
boolean autoRegisterComponent(in long aWhen, in nsIFile aComponent);
|
||||
|
||||
/**
|
||||
* AutoUnregister the given component.
|
||||
* Returns true if the component was unregistered, false if it coudln't
|
||||
* attempt to unregister the component (not found, wrong type).
|
||||
*/
|
||||
boolean autoUnregisterComponent(in long aWhen, in nsIFile aComponent);
|
||||
|
||||
/**
|
||||
* Register any deferred (NS_ERROR_FACTORY_REGISTER_AGAIN) components.
|
||||
* Return registered-any-components?
|
||||
*/
|
||||
boolean registerDeferredComponents(in long aWhen);
|
||||
|
||||
/**
|
||||
* Unload all components that are willing.
|
||||
*/
|
||||
void unloadAll(in long aWhen);
|
||||
|
||||
};
|
|
@ -61,13 +61,12 @@ interface nsIComponentRegistrar : nsISupports
|
|||
*
|
||||
* @param aSpec : Filename spec for component file's location. If aSpec
|
||||
* is a directory, then every component file in the
|
||||
* directory will be registered.
|
||||
* If the aSpec is null, then the application component's
|
||||
* directory as defined by NS_XPCOM_COMPONENT_DIR will be
|
||||
* registered (see nsIDirectoryService.idl)
|
||||
*
|
||||
* @return NS_OK : Registration was successful.
|
||||
* NS_ERROR: Method failure.
|
||||
* directory will be registered.
|
||||
* If aSpec is null, static components, GRE components,
|
||||
* and the application's component directories will be
|
||||
* registered. See NS_GRE_DIR, NS_XPCOM_COMPONENT_DIR,
|
||||
* and NS_XPCOM_COMPONENT_DIR_LIST in
|
||||
* nsDirectoryServiceDefs.h.
|
||||
*/
|
||||
void autoRegister(in nsIFile aSpec);
|
||||
|
||||
|
|
|
@ -11,11 +11,13 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is XPCOM.
|
||||
* The Original Code is Mozilla XPCOM.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
* The Initial Developer of the Original Code is
|
||||
* Benjamin Smedberg <benjamin@smedbergs.us>
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
|
@ -33,40 +35,30 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* The nsIComponentRegistrar interface.
|
||||
* @status EXPERIMENTAL
|
||||
*
|
||||
* USE AT YOUR OWN RISK
|
||||
* USE AT YOUR OWN RISK
|
||||
* USE AT YOUR OWN RISK
|
||||
* USE AT YOUR OWN RISK
|
||||
* USE AT YOUR OWN RISK
|
||||
* USE AT YOUR OWN RISK
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIFile;
|
||||
interface nsILocalFile;
|
||||
interface nsIModule;
|
||||
|
||||
[uuid(fce83d37-a3c0-4e09-ad9f-6842a984dbdf)]
|
||||
interface nsIComponentLoaderManager : nsISupports
|
||||
/**
|
||||
* Module loaders are responsible for loading a component file. The static
|
||||
* component loader is special and does not use this interface.
|
||||
*
|
||||
* @note Implementations of this interface should be threadsafe,
|
||||
* methods may be called from any thread.
|
||||
*/
|
||||
[scriptable, uuid(9b328e24-4d85-4a9c-9cb7-f25e66f430c3)]
|
||||
interface nsIModuleLoader : nsISupports
|
||||
{
|
||||
boolean hasFileChanged(in nsIFile file, in string loaderString, in PRInt64 modDate);
|
||||
void saveFileInfo(in nsIFile file, in string loaderString, in PRInt64 modDate);
|
||||
void removeFileInfo(in nsIFile file, in string loaderString);
|
||||
void flushPersistentStore(in boolean now);
|
||||
|
||||
string getOptionalData(in nsIFile file, in string loaderString);
|
||||
void setOptionalData(in nsIFile file, in string loaderString, in string value);
|
||||
/**
|
||||
* Return the module for a specified file. The module loader should
|
||||
* cache the module and return the same module for subsequent
|
||||
* requests for the same physical file. The module loader is
|
||||
* responsible for unloading the module during shutdown.
|
||||
*
|
||||
* @throws NS_ERROR_INVALID_ARG If the filename is not recognized.
|
||||
* @throws NS_ERROR_FACTORY_NOT_LOADED If the filename is recognized but
|
||||
* the module fails to load, e.g.: missing symbols, syntax errors
|
||||
*/
|
||||
nsIModule loadModule(in nsILocalFile aFile);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -35,48 +35,43 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsNativeModuleLoader_h__
|
||||
#define nsNativeModuleLoader_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIComponentLoader.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsDirectoryService.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsIModuleLoader.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "xcDll.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "prlink.h"
|
||||
|
||||
#ifndef nsNativeComponentLoader_h__
|
||||
#define nsNativeComponentLoader_h__
|
||||
|
||||
class nsNativeComponentLoader : public nsIComponentLoader
|
||||
class nsNativeModuleLoader : public nsIModuleLoader
|
||||
{
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICOMPONENTLOADER
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIMODULELOADER
|
||||
|
||||
nsNativeComponentLoader();
|
||||
|
||||
nsIComponentManager* mCompMgr; // weak reference -- backpointer
|
||||
nsNativeModuleLoader() {}
|
||||
~nsNativeModuleLoader() {}
|
||||
|
||||
nsresult Init();
|
||||
|
||||
void UnloadLibraries();
|
||||
|
||||
private:
|
||||
nsObjectHashtable mDllStore;
|
||||
nsVoidArray mDeferredComponents;
|
||||
struct NativeLoadData
|
||||
{
|
||||
nsCOMPtr<nsIModule> module;
|
||||
PRLibrary *library;
|
||||
};
|
||||
|
||||
~nsNativeComponentLoader() {}
|
||||
static PLDHashOperator
|
||||
ReleaserFunc(nsIHashable* aHashedFile, NativeLoadData &aLoadData, void*);
|
||||
|
||||
NS_IMETHOD RegisterComponentsInDir(PRInt32 when, nsIFile *dir);
|
||||
static PLDHashOperator
|
||||
UnloaderFunc(nsIHashable* aHashedFile, NativeLoadData &aLoadData, void*);
|
||||
|
||||
nsresult CreateDll(nsIFile *aSpec, const char *aLocation, nsDll **aDll);
|
||||
nsresult SelfRegisterDll(nsDll *dll, const char *registryLocation,
|
||||
PRBool deferred);
|
||||
nsresult SelfUnregisterDll(nsDll *dll);
|
||||
nsresult GetFactoryFromModule(nsDll *aDll, const nsCID &aCID,
|
||||
nsIFactory **aFactory);
|
||||
|
||||
nsresult DumpLoadError(nsDll *dll,
|
||||
const char *aCallerName,
|
||||
const char *aNsprErrorMsg);
|
||||
nsDataHashtable<nsHashableHashKey, NativeLoadData> mLibraries;
|
||||
};
|
||||
|
||||
#endif /* nsNativeComponentLoader_h__ */
|
||||
|
||||
#endif /* nsNativeModuleLoader_h__ */
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsIServiceManagerObsolete.h"
|
||||
#include "nsComponentManager.h"
|
||||
#include "nsIModule.h"
|
||||
|
||||
extern PRBool gXPCOMShuttingDown;
|
||||
|
||||
|
|
|
@ -36,13 +36,14 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXPCOMPrivate.h"
|
||||
#include "nsStaticComponentLoader.h"
|
||||
|
||||
#include "nsComponentManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "pldhash.h"
|
||||
|
||||
#include "nsIComponentLoader.h"
|
||||
#include "nsIModule.h"
|
||||
|
||||
#include "nsVoidArray.h"
|
||||
#include "pldhash.h"
|
||||
#include NEW_H
|
||||
#include "prlog.h"
|
||||
|
||||
|
@ -62,37 +63,6 @@ struct StaticModuleInfo : public PLDHashEntryHdr {
|
|||
StaticModuleInfo *next;
|
||||
};
|
||||
|
||||
class nsStaticComponentLoader : public nsIComponentLoader
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICOMPONENTLOADER
|
||||
|
||||
nsStaticComponentLoader() :
|
||||
mAutoRegistered(PR_FALSE),
|
||||
mFirst(nsnull)
|
||||
{ }
|
||||
|
||||
nsresult Init(nsStaticModuleInfo const *aStaticModules,
|
||||
PRUint32 aModuleCount);
|
||||
|
||||
private:
|
||||
~nsStaticComponentLoader() {
|
||||
if (mInfoHash.ops)
|
||||
PL_DHashTableFinish(&mInfoHash);
|
||||
}
|
||||
|
||||
protected:
|
||||
nsresult GetInfoFor(const char *aLocation, StaticModuleInfo **retval);
|
||||
|
||||
PRBool mAutoRegistered;
|
||||
nsCOMPtr<nsIComponentManager> mComponentMgr;
|
||||
PLDHashTable mInfoHash;
|
||||
static PLDHashTableOps sInfoHashOps;
|
||||
nsVoidArray mDeferredComponents;
|
||||
StaticModuleInfo *mFirst;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(void)
|
||||
info_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
||||
{
|
||||
|
@ -109,18 +79,16 @@ info_InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, const void *key)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/* static */ PLDHashTableOps nsStaticComponentLoader::sInfoHashOps = {
|
||||
/* static */ PLDHashTableOps nsStaticModuleLoader::sInfoHashOps = {
|
||||
PL_DHashAllocTable, PL_DHashFreeTable,
|
||||
PL_DHashGetKeyStub, PL_DHashStringKey, PL_DHashMatchStringKey,
|
||||
PL_DHashMoveEntryStub, info_ClearEntry,
|
||||
PL_DHashFinalizeStub, info_InitEntry
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsStaticComponentLoader, nsIComponentLoader)
|
||||
|
||||
nsresult
|
||||
nsStaticComponentLoader::Init(nsStaticModuleInfo const *aStaticModules,
|
||||
PRUint32 aModuleCount)
|
||||
nsStaticModuleLoader::Init(nsStaticModuleInfo const *aStaticModules,
|
||||
PRUint32 aModuleCount)
|
||||
{
|
||||
if (!PL_DHashTableInit(&mInfoHash, &sInfoHashOps, nsnull,
|
||||
sizeof(StaticModuleInfo), 1024)) {
|
||||
|
@ -153,9 +121,26 @@ nsStaticComponentLoader::Init(nsStaticModuleInfo const *aStaticModules,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsStaticModuleLoader::EnumerateModules(StaticLoaderCallback cb,
|
||||
nsTArray<DeferredModule> &deferred)
|
||||
{
|
||||
for (StaticModuleInfo *c = mFirst; c; c = c->next) {
|
||||
if (!c->module) {
|
||||
nsresult rv = c->info.
|
||||
getModule(nsComponentManagerImpl::gComponentManager, nsnull,
|
||||
getter_AddRefs(c->module));
|
||||
LOG(("nSCL: EnumerateModules(): %lx\n", rv));
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
}
|
||||
cb(c->info.name, c->module, deferred);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStaticComponentLoader::GetInfoFor(const char *aLocation,
|
||||
StaticModuleInfo **retval)
|
||||
nsStaticModuleLoader::GetModuleFor(const char *aLocation,
|
||||
nsIModule* *aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
StaticModuleInfo *info =
|
||||
|
@ -167,146 +152,14 @@ nsStaticComponentLoader::GetInfoFor(const char *aLocation,
|
|||
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
||||
|
||||
if (!info->module) {
|
||||
rv = info->info.getModule(mComponentMgr, nsnull,
|
||||
getter_AddRefs(info->module));
|
||||
LOG(("nSCL: GetInfoFor(\"%s\"): %lx\n", aLocation, rv));
|
||||
rv = info->info.
|
||||
getModule(nsComponentManagerImpl::gComponentManager, nsnull,
|
||||
getter_AddRefs(info->module));
|
||||
LOG(("nSCL: GetModuleForFor(\"%s\"): %lx\n", aLocation, rv));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
*retval = info;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStaticComponentLoader::Init(nsIComponentManager *mgr, nsISupports *aReg)
|
||||
{
|
||||
mComponentMgr = mgr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStaticComponentLoader::AutoRegisterComponents(PRInt32 when, nsIFile *dir)
|
||||
{
|
||||
if (mAutoRegistered)
|
||||
return NS_OK;
|
||||
|
||||
// if a directory has been explicitly specified, then return early. we
|
||||
// don't load static components from disk ;)
|
||||
if (dir)
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
StaticModuleInfo *info = mFirst;
|
||||
|
||||
while (info) {
|
||||
if (!info->module) {
|
||||
rv = info->info.getModule(mComponentMgr, nsnull, getter_AddRefs(info->module));
|
||||
LOG(("nSCL: getModule(\"%s\"): %lx\n", info->info.name, rv));
|
||||
if (NS_FAILED(rv) || !info->module)
|
||||
continue; // oh well
|
||||
}
|
||||
|
||||
rv = info->module->RegisterSelf(mComponentMgr, nsnull, info->info.name,
|
||||
staticComponentType);
|
||||
LOG(("nSCL: autoreg of \"%s\": %lx\n", info->info.name, rv));
|
||||
|
||||
if (rv == NS_ERROR_FACTORY_REGISTER_AGAIN)
|
||||
mDeferredComponents.AppendElement(info);
|
||||
|
||||
info = info->next;
|
||||
}
|
||||
|
||||
mAutoRegistered = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStaticComponentLoader::AutoUnregisterComponent(PRInt32 when,
|
||||
nsIFile *component,
|
||||
PRBool *retval)
|
||||
{
|
||||
*retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStaticComponentLoader::AutoRegisterComponent(PRInt32 when, nsIFile *component,
|
||||
PRBool *retval)
|
||||
{
|
||||
*retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStaticComponentLoader::RegisterDeferredComponents(PRInt32 when,
|
||||
PRBool *aRegistered)
|
||||
{
|
||||
*aRegistered = PR_FALSE;
|
||||
if (!mDeferredComponents.Count())
|
||||
return NS_OK;
|
||||
|
||||
for (int i = mDeferredComponents.Count() - 1; i >= 0; i--) {
|
||||
StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *,
|
||||
mDeferredComponents[i]);
|
||||
nsresult rv = info->module->RegisterSelf(mComponentMgr, nsnull,
|
||||
info->info.name,
|
||||
staticComponentType);
|
||||
if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
|
||||
if (NS_SUCCEEDED(rv))
|
||||
*aRegistered = PR_TRUE;
|
||||
mDeferredComponents.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStaticComponentLoader::OnRegister(const nsCID &aCID, const char *aType,
|
||||
const char *aClassName,
|
||||
const char *aContractID,
|
||||
const char *aLocation,
|
||||
PRBool aReplace, PRBool aPersist)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStaticComponentLoader::UnloadAll(PRInt32 aWhen)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStaticComponentLoader::GetFactory(const nsCID &aCID, const char *aLocation,
|
||||
const char *aType, nsIFactory **_retval)
|
||||
{
|
||||
StaticModuleInfo *info;
|
||||
nsresult rv;
|
||||
|
||||
if (NS_FAILED(rv = GetInfoFor(aLocation, &info)))
|
||||
return rv;
|
||||
|
||||
return info->module->GetClassObject(mComponentMgr, aCID,
|
||||
NS_GET_IID(nsIFactory),
|
||||
(void **)_retval);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NewStaticComponentLoader(nsStaticModuleInfo const *aStaticModules,
|
||||
PRUint32 aStaticModuleCount,
|
||||
nsIComponentLoader **retval)
|
||||
{
|
||||
nsCOMPtr<nsStaticComponentLoader> lthis = new nsStaticComponentLoader();
|
||||
if (!lthis)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = ((nsStaticComponentLoader*) lthis)->
|
||||
Init(aStaticModules, aStaticModuleCount);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
NS_ADDREF(*retval = lthis);
|
||||
NS_ADDREF(*aResult = info->module);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org Code. This file was copied
|
||||
* from nsStaticComponentLoader.cpp
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benjamin Smedberg <benjamin@smedbergs.us>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsStaticModuleLoader_h__
|
||||
#define nsStaticModuleLoader_h__
|
||||
|
||||
#include "nsXPCOM.h"
|
||||
#include "pldhash.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIModule;
|
||||
struct StaticModuleInfo;
|
||||
class nsComponentManagerImpl;
|
||||
struct DeferredModule;
|
||||
|
||||
typedef void (*StaticLoaderCallback)(const char *key,
|
||||
nsIModule* module,
|
||||
nsTArray<DeferredModule> &deferred);
|
||||
|
||||
class nsStaticModuleLoader
|
||||
{
|
||||
public:
|
||||
nsStaticModuleLoader() :
|
||||
mFirst(nsnull)
|
||||
{ }
|
||||
|
||||
nsresult Init(nsStaticModuleInfo const *aStaticModules,
|
||||
PRUint32 aModuleCount);
|
||||
|
||||
~nsStaticModuleLoader() {
|
||||
if (mInfoHash.ops)
|
||||
PL_DHashTableFinish(&mInfoHash);
|
||||
}
|
||||
|
||||
void EnumerateModules(StaticLoaderCallback cb,
|
||||
nsTArray<DeferredModule> &deferred);
|
||||
nsresult GetModuleFor(const char *key, nsIModule* *aResult);
|
||||
|
||||
private:
|
||||
PLDHashTable mInfoHash;
|
||||
static PLDHashTableOps sInfoHashOps;
|
||||
StaticModuleInfo *mFirst;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,336 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* nsDll
|
||||
*
|
||||
* Abstraction of a Dll. Stores modifiedTime and size for easy detection of
|
||||
* change in dll.
|
||||
*
|
||||
* dp Suresh <dp@netscape.com>
|
||||
*/
|
||||
|
||||
#include "xcDll.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIComponentLoaderManager.h"
|
||||
#include "nsIModule.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsString.h"
|
||||
#include "nsITimelineService.h"
|
||||
#include "nsModule.h"
|
||||
#ifdef DEBUG
|
||||
#if defined(VMS)
|
||||
#include <lib$routines.h>
|
||||
#include <ssdef.h>
|
||||
#elif defined(XP_MACOSX)
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#endif /* defined(DEBUG) */
|
||||
|
||||
#include "nsTraceRefcntImpl.h"
|
||||
|
||||
#define UNLOAD_DEPENDENT_LIBS
|
||||
#ifdef HPUX
|
||||
#undef UNLOAD_DEPENDENT_LIBS
|
||||
#endif
|
||||
|
||||
#include "nsNativeComponentLoader.h"
|
||||
|
||||
nsDll::nsDll(nsIFile *dllSpec, nsNativeComponentLoader *loader)
|
||||
: m_dllSpec(do_QueryInterface(dllSpec)),
|
||||
m_instance(NULL),
|
||||
m_moduleObject(NULL),
|
||||
m_loader(loader),
|
||||
m_markForUnload(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(loader, "Null loader when creating a nsDLL");
|
||||
}
|
||||
|
||||
nsDll::~nsDll(void)
|
||||
{
|
||||
//#if DEBUG_dougt
|
||||
// The dll gets deleted when the dllStore is destroyed. This happens on
|
||||
// app shutdown. At that point, unloading dlls can cause crashes if we have
|
||||
// - dll dependencies
|
||||
// - callbacks
|
||||
// - static dtors
|
||||
// Hence turn it back on after all the above have been removed.
|
||||
//Unload();
|
||||
//#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsDll::GetDisplayPath(nsACString& aLeafName)
|
||||
{
|
||||
m_dllSpec->GetNativeLeafName(aLeafName);
|
||||
|
||||
if (aLeafName.IsEmpty())
|
||||
aLeafName.AssignLiteral("unknown!");
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDll::HasChanged()
|
||||
{
|
||||
nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
|
||||
if (!manager)
|
||||
return PR_TRUE;
|
||||
|
||||
// If mod date has changed, then dll has changed
|
||||
PRInt64 currentDate;
|
||||
nsresult rv = m_dllSpec->GetLastModifiedTime(¤tDate);
|
||||
if (NS_FAILED(rv))
|
||||
return PR_TRUE;
|
||||
PRBool changed = PR_TRUE;
|
||||
manager->HasFileChanged(m_dllSpec, nsnull, currentDate, &changed);
|
||||
return changed;
|
||||
}
|
||||
|
||||
PRBool nsDll::Load(void)
|
||||
{
|
||||
if (m_instance != NULL)
|
||||
{
|
||||
// Already loaded
|
||||
return (PR_TRUE);
|
||||
}
|
||||
|
||||
if (m_dllSpec)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
|
||||
#endif
|
||||
|
||||
// load the component
|
||||
nsCOMPtr<nsILocalFile> lf(do_QueryInterface(m_dllSpec));
|
||||
NS_ASSERTION(lf, "nsIFile here must implement a nsILocalFile");
|
||||
lf->Load(&m_instance);
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
|
||||
if (m_instance) {
|
||||
// Inform refcnt tracer of new library so that calls through the
|
||||
// new library can be traced.
|
||||
nsXPIDLCString displayPath;
|
||||
GetDisplayPath(displayPath);
|
||||
nsTraceRefcntImpl::LoadLibrarySymbols(displayPath.get(), m_instance);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
|
||||
// Debugging help for components. Component dlls need to have their
|
||||
// symbols loaded before we can put a breakpoint in the debugger.
|
||||
// This will help figureing out the point when the dll was loaded.
|
||||
nsXPIDLCString displayPath;
|
||||
GetDisplayPath(displayPath);
|
||||
BreakAfterLoad(displayPath.get());
|
||||
#endif
|
||||
|
||||
return ((m_instance == NULL) ? PR_FALSE : PR_TRUE);
|
||||
}
|
||||
|
||||
PRBool nsDll::Unload(void)
|
||||
{
|
||||
if (m_instance == NULL)
|
||||
return (PR_FALSE);
|
||||
|
||||
// Shutdown the dll
|
||||
Shutdown();
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
|
||||
#endif
|
||||
PRStatus ret = PR_UnloadLibrary(m_instance);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
|
||||
#endif
|
||||
|
||||
if (ret == PR_SUCCESS)
|
||||
{
|
||||
m_instance = NULL;
|
||||
return (PR_TRUE);
|
||||
}
|
||||
else
|
||||
return (PR_FALSE);
|
||||
}
|
||||
|
||||
void * nsDll::FindSymbol(const char *symbol)
|
||||
{
|
||||
if (symbol == NULL)
|
||||
return (NULL);
|
||||
|
||||
// If not already loaded, load it now.
|
||||
if (Load() != PR_TRUE)
|
||||
return (NULL);
|
||||
|
||||
return(PR_FindSymbol(m_instance, symbol));
|
||||
}
|
||||
|
||||
|
||||
// Component dll specific functions
|
||||
nsresult nsDll::GetDllSpec(nsIFile **fsobj)
|
||||
{
|
||||
NS_ASSERTION(m_dllSpec, "m_dllSpec NULL");
|
||||
NS_ASSERTION(fsobj, "xcDll::GetModule : Null argument" );
|
||||
|
||||
*fsobj = m_dllSpec;
|
||||
NS_ADDREF(*fsobj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDll::GetModule(nsISupports *servMgr, nsIModule **cobj)
|
||||
{
|
||||
// using the backpointer of the loader.
|
||||
nsIComponentManager* compMgr = m_loader->mCompMgr;
|
||||
NS_ASSERTION(compMgr, "Global Component Manager is null" );
|
||||
if (!compMgr) return NS_ERROR_UNEXPECTED;
|
||||
|
||||
NS_ASSERTION(cobj, "xcDll::GetModule : Null argument" );
|
||||
|
||||
if (m_moduleObject)
|
||||
{
|
||||
NS_ADDREF(m_moduleObject);
|
||||
*cobj = m_moduleObject;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If not already loaded, load it now.
|
||||
if (Load() != PR_TRUE) return NS_ERROR_FAILURE;
|
||||
|
||||
// We need a nsIFile for location
|
||||
if (!m_dllSpec)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsGetModuleProc proc =
|
||||
(nsGetModuleProc) FindSymbol(NS_GET_MODULE_SYMBOL);
|
||||
|
||||
if (proc == NULL)
|
||||
return NS_ERROR_FACTORY_NOT_LOADED;
|
||||
|
||||
nsresult rv = (*proc) (compMgr, m_dllSpec, &m_moduleObject);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
NS_ADDREF(m_moduleObject);
|
||||
*cobj = m_moduleObject;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// These are used by BreakAfterLoad, below.
|
||||
#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
|
||||
static nsCString *sBreakList[16];
|
||||
static int sBreakListCount = 0;
|
||||
#endif
|
||||
|
||||
nsresult nsDll::Shutdown(void)
|
||||
{
|
||||
// Release the module object if we got one
|
||||
nsrefcnt refcnt;
|
||||
if (m_moduleObject)
|
||||
{
|
||||
NS_RELEASE2(m_moduleObject, refcnt);
|
||||
NS_ASSERTION(refcnt == 0, "Dll moduleObject refcount non zero");
|
||||
}
|
||||
#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
|
||||
for (int i = 0; i < sBreakListCount; i++)
|
||||
{
|
||||
delete sBreakList[i];
|
||||
sBreakList[i] = nsnull;
|
||||
}
|
||||
sBreakListCount = 0;
|
||||
#endif
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
|
||||
void nsDll::BreakAfterLoad(const char *nsprPath)
|
||||
{
|
||||
static PRBool firstTime = PR_TRUE;
|
||||
|
||||
// return if invalid input
|
||||
if (!nsprPath || !*nsprPath) return;
|
||||
|
||||
// return if nothing to break on
|
||||
if (!firstTime && sBreakListCount == 0) return;
|
||||
|
||||
if (firstTime)
|
||||
{
|
||||
firstTime = PR_FALSE;
|
||||
// Form the list of dlls to break on load
|
||||
nsCAutoString envList(getenv("XPCOM_BREAK_ON_LOAD"));
|
||||
if (envList.IsEmpty()) return;
|
||||
PRInt32 ofset = 0;
|
||||
PRInt32 start = 0;
|
||||
do
|
||||
{
|
||||
ofset = envList.FindChar(':', start);
|
||||
sBreakList[sBreakListCount] = new nsCString();
|
||||
envList.Mid(*(sBreakList[sBreakListCount]), start, ofset);
|
||||
sBreakListCount++;
|
||||
start = ofset + 1;
|
||||
}
|
||||
while (ofset != -1 && 16 > sBreakListCount); // avoiding vc6.0 compiler issue. count < thinks it is starting a template
|
||||
}
|
||||
|
||||
// Find the dllname part of the string
|
||||
nsCString currentPath(nsprPath);
|
||||
PRInt32 lastSep = currentPath.RFindCharInSet(":\\/");
|
||||
|
||||
for (int i=0; i<sBreakListCount; i++)
|
||||
if (currentPath.Find(*(sBreakList[i]), PR_TRUE, lastSep) > 0)
|
||||
{
|
||||
// Loading a dll that we want to break on
|
||||
// Put your breakpoint here
|
||||
fprintf(stderr, "...Loading module %s\n", nsprPath);
|
||||
// Break in the debugger here.
|
||||
#if defined(__i386) && defined(__GNUC__)
|
||||
asm("int $3");
|
||||
#elif defined(VMS)
|
||||
lib$signal(SS$_DEBUG);
|
||||
#elif defined(XP_MACOSX)
|
||||
raise(SIGTRAP);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif /* SHOULD_IMPLEMENT_BREAKAFTERLOAD */
|
|
@ -1,121 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Dll
|
||||
*
|
||||
* Programmatic representation of a dll. Stores modifiedTime and size for
|
||||
* easy detection of change in dll.
|
||||
*
|
||||
* dp Suresh <dp@netscape.com>
|
||||
*/
|
||||
|
||||
#ifndef xcDll_h__
|
||||
#define xcDll_h__
|
||||
|
||||
#include "prio.h"
|
||||
#include "prlink.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsNativeComponentLoader;
|
||||
|
||||
#if defined(DEBUG) && !defined(XP_BEOS)
|
||||
#define SHOULD_IMPLEMENT_BREAKAFTERLOAD
|
||||
#endif
|
||||
|
||||
class nsIModule;
|
||||
class nsIServiceManager;
|
||||
|
||||
typedef enum nsDllStatus
|
||||
{
|
||||
DLL_OK = 0,
|
||||
DLL_NO_MEM = 1,
|
||||
DLL_STAT_ERROR = 2,
|
||||
DLL_NOT_FILE = 3,
|
||||
DLL_INVALID_PARAM = 4
|
||||
} nsDllStatus;
|
||||
|
||||
class nsDll
|
||||
{
|
||||
private:
|
||||
nsCOMPtr<nsIFile> m_dllSpec;
|
||||
PRLibrary *m_instance;
|
||||
nsIModule *m_moduleObject;
|
||||
nsNativeComponentLoader *m_loader;
|
||||
PRBool m_markForUnload;
|
||||
|
||||
void Init(nsIFile *dllSpec);
|
||||
|
||||
#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
|
||||
void BreakAfterLoad(const char *nsprPath);
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
nsDll(nsIFile *dllSpec, nsNativeComponentLoader* loader);
|
||||
~nsDll(void);
|
||||
|
||||
// Dll Loading
|
||||
PRBool Load(void);
|
||||
PRBool Unload(void);
|
||||
PRBool IsLoaded(void)
|
||||
{
|
||||
return ((m_instance != 0) ? PR_TRUE : PR_FALSE);
|
||||
}
|
||||
void MarkForUnload(PRBool mark) { m_markForUnload = mark; }
|
||||
PRBool IsMarkedForUnload(void) { return m_markForUnload; }
|
||||
|
||||
// Shutdown the dll. This will call any on unload hook for the dll.
|
||||
// This won't unload the dll. Unload() implicitly calls Shutdown().
|
||||
nsresult Shutdown(void);
|
||||
|
||||
void *FindSymbol(const char *symbol);
|
||||
|
||||
PRBool HasChanged(void);
|
||||
|
||||
void GetDisplayPath(nsACString& string);
|
||||
|
||||
PRLibrary *GetInstance(void) { return (m_instance); }
|
||||
|
||||
// NS_RELEASE() is required to be done on objects returned
|
||||
nsresult GetDllSpec(nsIFile **dllSpec);
|
||||
nsresult GetModule(nsISupports *servMgr, nsIModule **mobj);
|
||||
};
|
||||
|
||||
#endif /* xcDll_h__ */
|
|
@ -54,7 +54,7 @@ NS_strspnp(const char *delims, const char *str);
|
|||
|
||||
/**
|
||||
* Tokenize a string. This function is similar to the strtok function in the
|
||||
* C standard library, but it does use static variables to maintain state
|
||||
* C standard library, but it does not use static variables to maintain state
|
||||
* and is therefore thread and reentrancy-safe.
|
||||
*
|
||||
* Any leading delimiters in str are skipped. Then the string is scanned
|
||||
|
|
|
@ -380,6 +380,18 @@ class nsTArray : public nsTArray_base {
|
|||
return ReplaceElementsAt(index, 0, &elem, 1);
|
||||
}
|
||||
|
||||
// Insert a new element without copy-constructing. This is useful to avoid
|
||||
// temporaries.
|
||||
// @return A pointer to the newly inserted element, or null on OOM.
|
||||
elem_type* InsertElementAt(index_type index) {
|
||||
if (!EnsureCapacity(Length() + 1, sizeof(elem_type)))
|
||||
return nsnull;
|
||||
ShiftData(index, 0, 1, sizeof(elem_type));
|
||||
elem_type *elem = Elements() + index;
|
||||
elem_traits::Construct(elem);
|
||||
return elem;
|
||||
}
|
||||
|
||||
// This method appends elements to the end of this array.
|
||||
// @param array The elements to append to this array.
|
||||
// @param arrayLen The number of elements to append to this array.
|
||||
|
@ -402,6 +414,18 @@ class nsTArray : public nsTArray_base {
|
|||
return AppendElements(&elem, 1);
|
||||
}
|
||||
|
||||
// Append a new element without copy-constructing. This is useful to avoid
|
||||
// temporaries.
|
||||
// @return A pointer to the newly appended element, or null on OOM.
|
||||
elem_type* AppendElement() {
|
||||
if (!EnsureCapacity(Length() + 1, sizeof(elem_type)))
|
||||
return nsnull;
|
||||
elem_type *elem = Elements() + Length();
|
||||
elem_traits::Construct(elem);
|
||||
++mLength;
|
||||
return elem;
|
||||
}
|
||||
|
||||
// This method removes a range of elements from this array.
|
||||
// @param start The starting index of the elements to remove.
|
||||
// @param count The number of elements to remove.
|
||||
|
|
Загрузка…
Ссылка в новой задаче