{"id":147,"date":"2006-12-22T16:48:10","date_gmt":"2006-12-22T20:48:10","guid":{"rendered":"http:\/\/benjamin.smedbergs.us\/blog\/2006-12-22\/simplifying-xpcom-code-patterns\/"},"modified":"2006-12-22T16:48:10","modified_gmt":"2006-12-22T20:48:10","slug":"simplifying-xpcom-code-patterns","status":"publish","type":"post","link":"http:\/\/benjamin.smedbergs.us\/blog\/2006-12-22\/simplifying-xpcom-code-patterns\/","title":{"rendered":"Simplifying XPCOM Code Patterns"},"content":{"rendered":"<p>Code that uses XPCOM is frequently verbose. Take, for instance, the relatively simple act of creating a URI object from a string:<\/p>\n<pre>var ioservice = Components.classes[\"@mozilla.org\/network\/io-service;1\"].\r\n  getService(Components.interfaces.nsIIOService);\r\nvar uri = ioservice.newURI(uristring, null, null);<\/pre>\n<p>What if this code looked a lot more like a Python <tt>import <var>module<\/var><\/tt> statement?<\/p>\n<pre>const network = Components.modules[\"@mozilla.org\/network\"];\r\nvar uri = network.newURI(uristring, null, null);<\/pre>\n<p>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&#8217;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 <a href=\"http:\/\/developer.mozilla.org\/en\/docs\/nsIModule\">nsIModule<\/a> interface. To make the above code a reality we&#8217;d only need to give the module an identifier so that it could be accessed by name, and teach the necko module to implement <a href=\"http:\/\/developer.mozilla.org\/en\/docs\/nsIIOService\">nsIIOService<\/a>, with a little classinfo throw in for automatic interface flattening.<\/p>\n<p>With this technique, it is even be possible to load arbitrary files as XPCOM modules, without having to autoregister them in the global registry: <tt>extensionmodule = Components.loadModule(somefile)<\/tt>. <\/p>\n<p>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&#8217;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.<\/p>\n<p>Perhaps JS could even grow a &#8220;from foo import X, Y, Z&#8221; statement, in imitation of Python:<\/p>\n<pre>from Components.modules[\"@mozilla.org\/network\"] import newURI, newFileURI, newChannelFromURI;<\/pre>\n<h4>More Examples<\/h4>\n<p>Creating an nsIFile instance from a string path:<\/p>\n<pre>const XPCOM = Components.modules[\"@mozilla.org\/xpcom\"];\r\nvar file = XPCOM.File(spec);<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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[&#8220;@mozilla.org\/network\/io-service;1&#8221;]. getService(Components.interfaces.nsIIOService); 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[&#8220;@mozilla.org\/network&#8221;]; var uri = network.newURI(uristring, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[38],"class_list":["post-147","post","type-post","status-publish","format-standard","hentry","category-mozilla","tag-xpcom"],"_links":{"self":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts\/147","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/comments?post=147"}],"version-history":[{"count":0,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts\/147\/revisions"}],"wp:attachment":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/media?parent=147"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/categories?post=147"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/tags?post=147"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}