0

Considering the following example:

Components.utils.import('chrome://something/content/main.jsm');

// inside main.jsm
Components.utils.import('chrome://something/content/sub.jsm');

Does unloading main.jsm also unload sub.jsm or should sub.jsm be unloaded in addition to main.jsm?

Note: The unloading is part of shutdown() in Firefox bootstrapped addon.

erosman
  • 7,094
  • 7
  • 27
  • 46

1 Answers1

1

No, it will not.

All modules are standalone and shared from the perspective of the loader. Which makes sense since all modules are loaded exactly once in the application. Well, until you Cu.unload, of course; though a subsequent Cu.import for that module would then load it again like the initial load.

So, a module is shared between all code accessing it. This means that the following will happen:

other.jsm

EXPORTED_SYMBOLS = ['shared'];
shared = {abc:123};

bootstap.js

// Initial load of shared.jsm
Cu.import(".../other.jsm");
// Will be seen by all other modules, since this is shared. 
shared.def = 345;

// Will not propagate, as the top-level name shared is just a reference
// in the current scope, initially holding a reference to the object from shared,
// but now overriden.
shared = "string";

Cu.import(".../main.jsm");

main.jsm

// Since the module was already loaded before, the loader will not load it again
// but instead just use provide the references. 
Cu.import(".../other.jsm");

Cu.reportError(shared.abc); // 123
Cu.reportError(shared.def); // 456

This can come quite handy, e.g. when you need a central location to track/share/cache stuff, but also is a bit dangerous in regards to memory leaks on shutdown.

If you e.g. added another service getter to Services.jsm, e.g.:

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");

XPCOMUtils.defineLazyServiceGetter(Services, "uuid",
                                   "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");

Now that is problematic for two reasons:

  1. Services will (initially) keep references to those string arguments around. And those string strings are owned by your module. Cu.unloading your module will not fully destroy you module instance, since Services still references those strings, therefore your module cannot be fully garbage collected and your module instance would effectively become a Zombie Compartment.
  2. Since all other add-ons and also the browser code get the same Services. there might be name clashes when adding new stuff to it. Something else might have added a uuid property already.

Also, you should never Cu.unload modules that are not yours!

The unloading is part of shutdown() in Firefox bootstrapped addon.

Doesn't matter for the operation of Cu.unload. It will work the same, always.

nmaier
  • 32,336
  • 5
  • 63
  • 78