You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.



JavaScript XPCOM Components Status - Draft 2

Introduction

In the document XPJS Components Proposal I proposed that we build a system for implementing xpcom components and services in JavaScript - components that could be used transparently by any other xpcom components.

Mike Shaver has since done the work to make this system work. This document will explain the status of that work and will try to detail the limitations of the system as currently implemented.

Implementation

The system, of course, is all based on XPConnect. The main innovation was in factoring out the system that xpcom uses to instantiate components. Previously there was a builtin component loader that assumed that all components were implemented in C/C++ and either loaded from a DLL or via factory instances registered (non-persistently) at runtime. Mike broke this code out to build a plugable component loader system. He then wrote one loader for native components loaded from DLLs and one for JavaScript components loaded from .js files. This is an extensible system and we can expect that others will write additional loaders in the future.

The JS component loader implementation is in /js/src/xpconnect/loader/. As far as I know Mike Shaver did not write any detailed documentation about its use. In a nutshell... It will try to load for registration and use as a component any .js files it discovers in the 'components' directory during autoregistration time; i.e. the same directory where native components in DLLs are located. I'm not sure if it will attempt to discover these files everytime the app is started or only during autoregistration [shaver clarification?].

The best document that I know of is in the sample at xpcom/sample/nsSample.js. I think it worth noting that this is both a sample and a bit of a test bed. There is some unnecessary debug code. And the boilerplate code really ought to be reorganized a bit with the customizable part broken out as separate variables so that future JS component implementors can just copy the common blocks and fill in their own strings for progids and iids etc. Nevertheless, it is the sample we have and the comments in the sample explain how to use the system.

An additional source of info on the evolution of the system (for the hardcore curious) is the discussions on the xpcom newsgroup. Search the subjects for keywords like: JS components, component loader.

Any .js file that shows up in the components directory is a likely example of JS component usage. Currently, there is a sidebar component. Mike Shaver had implemented the category manager using JS, but it was reimplemented in C++. Not because its implementation in JS was not viable, but simply because it was decided that xpcom should not have a core service which required JavaScript and XPConnect. This would have limited xpcom's usefulness in some non-browser embeddings where JavaScript might not otherwise be needed or wanted.

Unwrapping

Until 1 August 2000 there was a 'killer' problem with JS Components... When used by JS code they did not 'look' like other xpcom components. The source of this problem was that xpconnect was giving the calling JS code direct access to the underlying JSObject of the JS Component. This meant that the caller had access to all of the methods and properties of the JS Component and was not limited by the declared interface. It also meant that other xpconnect infrastructure did not recognize the 'unwrapped' JS Component as being an implementation of any given xpcom interface. See the discussion of these problems here.

In the long run this will be fixed by a third sort of xpconnect wrapper which is specialized for this purpose. In the short run it was decided to 'double wrap' the JS Components when they are handed to JS code from native code. This means that when the JS Component is created and handed to native code xpconnect builds a wrapper to be used by the native code AND when that wrapper is later handed to JS code then xpconnect builds a wrapper around that wrapper for use from JS. This makes the JS Component nearly indistinguishable from native xpcom components. But there is one difference....

It is anticipated that in some rare cases the calling JS code might actually need to get access to the underlying JSObject of the JS Component. For this purpose xpconnect wrappers around xpcom components now support a property named wrappedJSObject. This allows JS code to do something like...

// 'foo' is an xpcom object that *might* be implemented in JS
var underlyingObject = foo.wrappedJSObject;
if(underlyingObject) {
   underlyingObject.somePropertyThatIsNotPartOfTheInterface = 'bar';
}

If 'foo' is not implemented in JS then foo.wrappedJSObject will return undefined. Also, even if 'foo' is implemeneted in JS this will only succeed if the underlying JSObject has a property called 'wrappedJSObject' which is set to a JSObject (typically the this of the JSObject). This means that only JS Componets that want to expose their underlying JSObject can be unwrapped this way. It also allows for those objects to return some other JSObject if they choose. XPConnect also supports having the security system do a special check before allowing this activity to succeed. But, for now, all such XPConnect activities are gated only they the UniversalXPConnect 'super-privilege'.

Bugs

  • 24688 - runtime errors in wrapped JS are not made obvious (FIXED)
  • 25180 - xpconnect needs wrappers for JS -> JS communication

    I've checked in an interim solution which 'double wraps' JS components when they are handed back to Js code. This is not particulary efficient. But it is better that simply unwrapping the JSObject as we did before.

  • 27867 - xpconnect does not always work well with DOM objects (FIXED)

Conclusions and Recommendations

I think that JavaScript components have a bright future. There are limitations that one must be aware of - especially when working with the DOM. But, JS Components are appropriate for many tasks.