在bootstrap插件中卸载懒惰的getter?

时间:2014-07-22 05:14:02

标签: javascript firefox-addon firefox-addon-restartless

bootstrap.js的顶部,我定义了一堆lazyGetter,而不是JSM:

const myServices = {};
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyGetter(myServices, 'sss', function(){ return Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService) });

我听说您必须unload导入模块。但是"模块"你为lazyGetter创建的?我该怎么卸载那些?我会做delete myServices吗?

如果我在delete上进行myServices全局,这是否意味着我应该在卸载时删除所有全局变量?

我在这里阅读:Forgetting to unload JavaScript modules in restartless add-ons

  

忘记在无重启加载项中卸载JavaScript模块

     

泄漏的另一个常见原因是忘记卸载JavaScript代码   bootstrapped加载项中的模块。无法检测到这些泄漏   看看:隔间或左右:内存,因为这样的模块   住在主系统隔间内。

     

此外,当您的加载项更新并重新启用时,前一个   将使用仍然加载的模块版本,这可能会中断   你的加载项完全。

     

以下示例说明如何再次卸载模块   (bootstrap.js):

Components.utils.import("resource://gre/modules/Services.jsm");

function startup(data, reason) {
  // This assumes your add-on did register some chrome
  Components.utils.import("chrome://myaddon/content/mymodule.jsm");
}

function shutdown(data, reason) {
  if (reason != APP_SHUTDOWN) {
    // No need to do regular clean up when the application is closed
    // unless you need to break circular references that might negatively
    // impact the shutdown process.
    return;
  }

  // Your add-on needs to unload all modules it ships and imported!
  Components.utils.unload("chrome://myaddon/content/mymodule.jsm");
}
     
    

注意:不属于您的加载项的模块(例如Services.jsm)不应由您的加载项卸载,因为这可能会导致错误和/或性能回归,并且实际上会增加内存使用量。

  

1 个答案:

答案 0 :(得分:2)

您提供的代码不会导入模块,而是定义服务获取器,所以没关系。

(旁白:还有XPCOMUtils.defineLazyServiceGetter helper ...)

但是如果你做了这样的事情:

XPCOMUtils.defineLazyGetter(myServices, 'SomeSymbol', function() {
   return Cu.import("chrome://myaddon/content/mymodule.jsm", {}).SomeSymbol;
});

然后你当然需要Cu.unload()那个模块。这是最好的(IMO),通过注册模块加载后立即卸载,如下所示:

XPCOMUtils.defineLazyGetter(myServices, 'SomeSymbol', function() {
   let rv = Cu.import("chrome://myaddon/content/mymodule.jsm", {}).SomeSymbol;
   unload(function() {
     Cu.unload("chrome://myaddon/content/mymodule.jsm");
   });
   return rv;
});

其他人只是主动卸载所有可能已导入的模块。这很好,因为Cu.unload()一个没有导入的模块什么都不做。

PS:在将某些东西粘贴到另一个模块中时,你仍然会遇到麻烦,例如。

XPCOMUtils.defineLazyServiceGetter(Services /* other module */,
                                   'sss',
                                   '@mozilla.org/content/style-sheet-service;1',
                                   'nsIStyleSheetService');

在此示例中,XPCOMUtils.jsm可能仍会引用从代码中作为参数传递的字符串,从而泄露代码。 (此外,将内容粘贴到不属于您自己的模块中可能会非常粗鲁,并且可能会与其他附加组件发生冲突,从而做同样的事情。)