1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
---|
2 |
|
---|
3 | /*
|
---|
4 | * No magic constructor behaviour, as is de rigeur for XPCOM.
|
---|
5 | * If you must perform some initialization, and it could possibly fail (even
|
---|
6 | * due to an out-of-memory condition), you should use an Init method, which
|
---|
7 | * can convey failure appropriately (thrown exception in JS,
|
---|
8 | * NS_FAILED(nsresult) return in C++).
|
---|
9 | *
|
---|
10 | * In JS, you can actually cheat, because a thrown exception will cause the
|
---|
11 | * CreateInstance call to fail in turn, but not all languages are so lucky.
|
---|
12 | * (Though ANSI C++ provides exceptions, they are verboten in Mozilla code
|
---|
13 | * for portability reasons -- and even when you're building completely
|
---|
14 | * platform-specific code, you can't throw across an XPCOM method boundary.)
|
---|
15 | */
|
---|
16 | function mySample() { /* big comment for no code, eh? */ }
|
---|
17 |
|
---|
18 | /* decorate prototype to provide ``class'' methods and property accessors */
|
---|
19 | mySample.prototype = {
|
---|
20 | /*
|
---|
21 | * get and set are new Magic in JS1.5, borrowing the intent -- if not
|
---|
22 | * the exact syntax -- from the JS2 design. They define accessors for
|
---|
23 | * properties on the JS object, follow the expected rules for prototype
|
---|
24 | * delegation, and make a mean cup of coffee.
|
---|
25 | */
|
---|
26 | get value() { return this.val; },
|
---|
27 | set value(newval) { return this.val = newval; },
|
---|
28 |
|
---|
29 | writeValue: function (aPrefix) {
|
---|
30 | debug("mySample::writeValue => " + aPrefix + this.val + "\n");
|
---|
31 | },
|
---|
32 | poke: function (aValue) { this.val = aValue; },
|
---|
33 |
|
---|
34 | QueryInterface: function (iid) {
|
---|
35 | if (iid.equals(Components.interfaces.nsISample) ||
|
---|
36 | iid.equals(Components.interfaces.nsISupports))
|
---|
37 | return this;
|
---|
38 |
|
---|
39 | Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
|
---|
40 | return null;
|
---|
41 | },
|
---|
42 |
|
---|
43 | val: "<default value>"
|
---|
44 | }
|
---|
45 |
|
---|
46 | var myModule = {
|
---|
47 | firstTime: true,
|
---|
48 |
|
---|
49 | /*
|
---|
50 | * RegisterSelf is called at registration time (component installation
|
---|
51 | * or the only-until-release startup autoregistration) and is responsible
|
---|
52 | * for notifying the component manager of all components implemented in
|
---|
53 | * this module. The fileSpec, location and type parameters are mostly
|
---|
54 | * opaque, and should be passed on to the registerComponent call
|
---|
55 | * unmolested.
|
---|
56 | */
|
---|
57 | registerSelf: function (compMgr, fileSpec, location, type) {
|
---|
58 | if (this.firstTime) {
|
---|
59 | debug("*** Deferring registration of sample JS components\n");
|
---|
60 | this.firstTime = false;
|
---|
61 | throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
|
---|
62 | }
|
---|
63 | debug("*** Registering sample JS components\n");
|
---|
64 | compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
---|
65 | compMgr.registerFactoryLocation(this.myCID,
|
---|
66 | "Sample JS Component",
|
---|
67 | this.myProgID,
|
---|
68 | fileSpec,
|
---|
69 | location,
|
---|
70 | type);
|
---|
71 | },
|
---|
72 |
|
---|
73 | /*
|
---|
74 | * The GetClassObject method is responsible for producing Factory objects
|
---|
75 | */
|
---|
76 | getClassObject: function (compMgr, cid, iid) {
|
---|
77 | if (!cid.equals(this.myCID))
|
---|
78 | throw Components.results.NS_ERROR_NO_INTERFACE;
|
---|
79 |
|
---|
80 | if (!iid.equals(Components.interfaces.nsIFactory))
|
---|
81 | throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
---|
82 |
|
---|
83 | return this.myFactory;
|
---|
84 | },
|
---|
85 |
|
---|
86 | /* CID for this class */
|
---|
87 | myCID: Components.ID("{dea98e50-1dd1-11b2-9344-8902b4805a2e}"),
|
---|
88 |
|
---|
89 | /* ProgID for this class */
|
---|
90 | myProgID: "@mozilla.org/jssample;1",
|
---|
91 |
|
---|
92 | /* factory object */
|
---|
93 | myFactory: {
|
---|
94 | /*
|
---|
95 | * Construct an instance of the interface specified by iid, possibly
|
---|
96 | * aggregating it with the provided outer. (If you don't know what
|
---|
97 | * aggregation is all about, you don't need to. It reduces even the
|
---|
98 | * mightiest of XPCOM warriors to snivelling cowards.)
|
---|
99 | */
|
---|
100 | createInstance: function (outer, iid) {
|
---|
101 | debug("CI: " + iid + "\n");
|
---|
102 | if (outer != null)
|
---|
103 | throw Components.results.NS_ERROR_NO_AGGREGATION;
|
---|
104 |
|
---|
105 | return (new mySample()).QueryInterface(iid);
|
---|
106 | }
|
---|
107 | },
|
---|
108 |
|
---|
109 | /*
|
---|
110 | * The canUnload method signals that the component is about to be unloaded.
|
---|
111 | * C++ components can return false to indicate that they don't wish to be
|
---|
112 | * unloaded, but the return value from JS components' canUnload is ignored:
|
---|
113 | * mark-and-sweep will keep everything around until it's no longer in use,
|
---|
114 | * making unconditional ``unload'' safe.
|
---|
115 | *
|
---|
116 | * You still need to provide a (likely useless) canUnload method, though:
|
---|
117 | * it's part of the nsIModule interface contract, and the JS loader _will_
|
---|
118 | * call it.
|
---|
119 | */
|
---|
120 | canUnload: function(compMgr) {
|
---|
121 | debug("*** Unloading sample JS components\n");
|
---|
122 | return true;
|
---|
123 | }
|
---|
124 | };
|
---|
125 |
|
---|
126 | function NSGetModule(compMgr, fileSpec) {
|
---|
127 | return myModule;
|
---|
128 | }
|
---|
129 |
|
---|
130 |
|
---|