考虑以下示例:

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

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


卸载main.jsm还会卸载sub.jsm吗?还是应该在sub.jsm之外卸载main.jsm

注意:卸载是Firefox自举插件中shutdown()的一部分。

最佳答案

不,不会。

所有模块都是独立的,从加载程序的角度来看是共享的。这是有道理的,因为所有模块在应用程序中仅加载一次。好吧,当然,直到您Cu.unload;尽管该模块的后续Cu.import随后将像初始加载一样再次加载它。

因此,模块在访问它的所有代码之间共享。这意味着将发生以下情况:

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


这可能非常方便,例如当您需要一个中央位置来跟踪/共享/缓存内容时,但是在关机时内存泄漏方面也有些危险。

如果您例如在Services.jsm中添加了另一个服务获取器,例如:

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

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


现在有问题的原因有两个:


Services将(最初)保留对这些字符串参数的引用。这些字符串由模块拥有。 Cu.unload装入模块不会完全破坏您的模块实例,因为Services仍引用那些字符串,因此无法完全垃圾回收您的模块,并且您的模块实例将有效地变为Zombie Compartment
由于所有其他附加组件以及浏览器代码也获得相同的服务。向其中添加新内容时,名称可能会发生冲突。其他可能已经添加了uuid属性。


另外,您绝对不要Cu.unload不是您自己的模块!


  卸载是Firefox自举插件中shutdown()的一部分。


Cu.unload的操作无关紧要。它将始终如一地工作。

10-04 17:16