2013-07-05

tombloo REL_0.4.23 fix a lot (for Fx4) 14:03

fix Components: use NSGetFactory, NSGetModule is obsolete

function NSGetModule(compMgr, fileSpec) {
	return {
		registerSelf : function(compMgr, fileSpec, location, type) {
			compMgr.QueryInterface(Ci.nsIComponentRegistrar).registerFactoryLocation(
				Module.CID, Module.NAME, Module.PID,
				fileSpec, location, type);

			Module.onRegister && Module.onRegister(compMgr, fileSpec, location, type);
		},
		canUnload : function(compMgr) {
			return true;
		},
 		getClassObject : function(compMgr, cid, iid){
			if (!cid.equals(Module.CID))
				throw Cr.NS_ERROR_NOT_IMPLEMENTED;

			if (!iid.equals(Ci.nsIFactory))
				throw Cr.NS_ERROR_NO_INTERFACE;

			Module.onInit && Module.onInit(compMgr, cid, iid);

			return {
				createInstance: function(outer, iid) {
					if (outer != null)
						throw Cr.NS_ERROR_NO_AGGREGATION;

					var obj = Module.createInstance(outer, iid);
					obj.wrappedJSObject = obj;
					return obj;
				}
			};
		},
	};
}
var ModuleImpl = {
	registerSelf : function(compMgr, fileSpec, location, type) {
		compMgr.QueryInterface(Ci.nsIComponentRegistrar).registerFactoryLocation(
			Module.CID, Module.NAME, Module.PID,
			fileSpec, location, type);

		Module.onRegister && Module.onRegister(compMgr, fileSpec, location, type);
	},
	canUnload : function(compMgr) {
		return true;
	},
	getClassObject : function(compMgr, cid, iid){
		if (!cid.equals(Module.CID)) {
			throw Cr.NS_ERROR_NO_INTERFACE;
		}

		if (!iid.equals(Ci.nsIFactory)) {
			throw Cr.NS_ERROR_NOT_IMPLEMENTED;
		}

		Module.onInit && Module.onInit(compMgr, cid, iid);

		return this.factory;
	},
	factory: {
		createInstance: function(outer, iid) {
			if (outer != null) {
				throw Cr.NS_ERROR_NO_AGGREGATION;
			}

			var obj = Module.createInstance(outer, iid);
			obj.Module = Module;
			obj.wrappedJSObject = obj;
			return obj;
		}
	}
};

function NSGetModule(compMgr, fileSpec) {
	return ModuleImpl;
}

function NSGetFactory(cid) {
	return ModuleImpl.factory;
}

14:08

なるほど。もともとは NSGetModule() に直接、定義されてた訳ね。で、Firefox4の NSGetFactory() のために ModuleImpl として切り出した、と。

14:09

なんで、そうなっているのか理解したかったら、履歴も見ないとダメですね。

Onion Peel View of XPCOM Component Creation 14:12

https://developer.mozilla.org/en-US/docs/Creating_XPCOM_Components/Creating_the_Component_Code#Onion_Peel_View_of_XPCOM_Component_Creation

Creating the Component Code - Creating XPCOM Components | MDN

In a way, the factory and module layers are glue to plug the XPCOM object into the larger XPCOM system.

One layer above the object itself is the nsIFactory object. This object provides basic abstraction of the XPCOM object itself. As you can see in Onion Peel View of XPCOM Component Creation, the main accessor for the XPCOM object is CreateInstance, which is expected to return the object that matches a given CID and IID pair.

Moving another layer outward is the nsIModule. This interface provides yet another abstraction of the nsIFactory object, and may allow for multiple nsIFactory objects. The key to this interface is that the return type of getClassObject does not have to be an nsIFactory. Instead, the nsIModule can ask for implementation details about the XPCOM object. This is very useful if the caller is required to know information about the component like its threading module, whether or not it's a singleton, its implementation language, and so forth. The interface used in this case is nsIClassInfo. Starting from the outside in, Onion Peel View of XPCOM Component Creation represents the sequence for constructing an XPCOM object.