javascript - 在引导插件中卸载惰性 setter/getter ?

标签 javascript firefox-addon firefox-addon-restartless

在我的bootstrap.js的顶部我定义了一堆lazyGetter s,而不是 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

如果我做 deletemyServices这是全局变量,这是否意味着我应该在卸载时删除所有全局变量?

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

Forgetting to unload JavaScript modules in restartless add-ons

Another common cause of leaks is forgetting to unload JavaScript code modules in bootstrapped add-ons. These leaks cannot be detected by looking at about:compartments or about:memory because such modules live within the main System compartment.

Also, when your add-on gets updated and re-enabled, the previous module version that is still loaded will be used, which might break your add-on entirely.

The following example shows how to unload your modules again (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");
}

Note: Modules not belonging to your add-on — such as Services.jsm — should not be unloaded by your add-on, as this might cause errors and/or performance regressions and will actually increase the memoryusage.

最佳答案

您提供的代码没有导入模块,而是定义了服务 getter,所以没问题。

(旁白:还有一个 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 可能仍会引用从代码中作为参数传递的字符串,从而泄漏您的代码。 (此外,将内容粘贴到不属于您自己的模块中是相当粗鲁的,并且可能会与执行相同操作的其他附加组件产生冲突。)

关于javascript - 在引导插件中卸载惰性 setter/getter ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24879400/

相关文章:

javascript - 如何从扩展中检测页面加载错误?

javascript - Components.utils.unload 在 Firefox 引导扩展中是异步的吗?

javascript - Firefox 插件读取本地 XPI、文件和目录列表

javascript - Firefox 键盘快捷键是否仅在浏览器启动时激活?

javascript - DAO 与 ORM - 在 Sequelize.js 的上下文中解释的概念

javascript - 如何实现点击 anchor 链接时平滑滚动到不同页面的部分?

javascript - HTMLElement 自定义事件

javascript 序列化 - 一个简短的库

jquery - 如何在 Firefox 插件中的脚本之间移动 jQuery 对象?

firefox-addon - 在 Firefox 的 browser.js 中调用 toggleSidebar