Simplifying XPCOM Code Patterns

Code that uses XPCOM is frequently verbose. Take, for instance, the relatively simple act of creating a URI object from a string:

var ioservice = Components.classes[";1"].
var uri = ioservice.newURI(uristring, null, null);

What if this code looked a lot more like a Python import module statement?

const network = Components.modules[""];
var uri = network.newURI(uristring, null, null);

This code is more readable, and is slightly more efficient. We could do this now, for Mozilla 1.9, in a backwards-compatible way that didn’t require any code changes for existing code (i.e. createInstance() and getService() would continue to work as they do today). We already have XPCOM modules, which currently only implement the nsIModule interface. To make the above code a reality we’d only need to give the module an identifier so that it could be accessed by name, and teach the necko module to implement nsIIOService, with a little classinfo throw in for automatic interface flattening.

With this technique, it is even be possible to load arbitrary files as XPCOM modules, without having to autoregister them in the global registry: extensionmodule = Components.loadModule(somefile).

There is at least one problem with this approach: it means that extensions could no longer override the IOService contractID. Back when XPCOM was being copied from MS-COM, this was considered a major advantage. I don’t believe that it ever worked well, and there are much better ways to achieve extensibility, for classes that are specifically designed to be overridden.

Perhaps JS could even grow a “from foo import X, Y, Z” statement, in imitation of Python:

from Components.modules[""] import newURI, newFileURI, newChannelFromURI;

More Examples

Creating an nsIFile instance from a string path:

const XPCOM = Components.modules[""];
var file = XPCOM.File(spec);

Atom Feed for Comments 4 Responses to “Simplifying XPCOM Code Patterns”

  1. Anonymous Says:

    “and there are much better ways to achieve extensibility, for classes that are specifically designed to be overridden”
    Extensions often try to achieve something which was not designed by the core application to be achievable, so there might be use cases making it important to override arbitrary components.

  2. pd Says:

    It is strange that you are making this point at the exact time I am looking at extension JS files wondering how others do what I want to do and seeing the assignmnets you refer to and wondering where I can find more information.

    At the same time Mark Finkle is asking potential and existing Extension hackers how to make life easier!

    Seeing Extensions like FireFTP and others use the calls like that above to various components (is that what they are?) like nsIAlertsServices, nsICryptoHash, nsILocalFile, nsIPrefBranch, nsIWindowMediator and nsIXMLHttpRequest leads of course to wondering what those cryptic strings really mean.

    Are these ‘components’ actually anything to do with XPCOM? What relationship do they have to C and or ‘the Mozilla platform’ and/or xulrunner for that matter.

    As I commented on Mark’s posting, I think not only can these ‘code patterns’ be simplified but I think they can be much better documented in terms of how they relate to the overall Mozilla ecosystem.

  3. Brendan Eich Says:

    In JS2/ES4 (see, packages are named by dotted identifier paths, and you can import * or selective names from a package. You can also rename when importing, to avoid local collisions. It would be helpful to see strawman proposals for Mozilla 2 API bindings of native C++ code, currently wrapped in XPCOM clothing, that reflect as JS2 packages.


  4. BSBlog » Blog Archive » Bound Functions and Function Imports in JavaScript Says:

    […] Bound Functions and Function Imports in JavaScript After playing with the code in my last post, and asking some apparently silly questions about the ES4 spec, I’ve found some techniques which can be used to implement python-style “import” using current JavaScript. […]

Leave a Reply