Categories
Mozilla

XPCOMUtils API Addition

We’ve recently added two new API’s on XPCOMUtils that make a common coding pattern simpler to do. It is quite common to have “smart getters” to store a reference to a service that you use in JavaScript. Normally, folks write code that looks something like this:

this.__defineGetter__("_ioService", function() {
  delete this._ioService;
  return this._ioService = Components.classes["@mozilla.org/network/io-service;1"].
                           getService(Components.interfaces.nsIIOService);
});


That gets long and verbose if you have any more than a few of these getters. The new approach looks like this:

XPCOMUtils.defineLazyServiceGetter(this, "_ioService",
                                   "@mozilla.org/network/io-service;1",
                                   "nsIIOService");


The net result is a lot less boilerplate code, which, in my opinion, is a lot nicer to read. I’ve already converted the toolkit code in the Places module over, and the resulting code is much nicer.

Sometimes, however, you want to have a getter for something that is not a service. That’s where the second API comes in. You can pass in a lambda function that will be called when the value is needed for the first time. From then on, the value is cached. Some old code may look something like this:

this.__defineGetter__("_db", function() {
  delete this._db;
  return this._db = Components.classes["@mozilla.org/browser/nav-history-service;1"].
                    getService(Components.interfaces.nsPIPlacesDatabase).
                    DBConnection;
});


With the new API, that code turns into this:

XPCOMUtils.defineLazyGetter(this, "_db", function() {
  return Components.classes["@mozilla.org/browser/nav-history-service;1"].
         getService(Components.interfaces.nsPIPlacesDatabase).
         DBConnection;
});


Again, much nicer looking! If you are interested, the implementation of these methods can be found here.