public
Last active

ff-addon-template: Template for how to create a JSM module.

  • Download Gist
_template-BootstrapJSM.xpi
bootstrap.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
const {utils: Cu} = Components;
const chromeModulesPath = 'chrome://bootstrap-jsm/content/';
//Cu.import(chromeModulesPath + '/helloWorld.jsm'); //we CANNOT import it here we must do it in startup otherwise we get this error: "WARN addons.xpi: Error loading bootstrap.js for Bootstrap-JSM@jetpack: [Exception... "Component returned failure code: 0x80070057 (NS_ERROR_ILLEGAL_VALUE) [nsIXPCComponents_Utils.import]" nsresult: "0x80070057 (NS_ERROR_ILLEGAL_VALUE)" location: "JS frame :: resource://gre/modules/XPIProvider.jsm -> jar:file:///C:/Documents%20and%20Settings/blah%20blah/Application%20Data/Mozilla/Firefox/Profiles/de83bb0q.default/extensions/Bootstrap-JSM@jetpack.xpi!/bootstrap.js :: <TOP_LEVEL> :: line 3" data: no]"
 
function startup(aData, aReason) {
Cu.import(chromeModulesPath + '/helloWorld.jsm'); //startup is the earliest we can import it
//BEGIN EXAMPLE USAGE
Cu.import('resource://gre/modules/Services.jsm');
var rWin = Services.wm.getMostRecentWindow(null);
rWin.alert('foo = ' + foo);
rWin.alert('bar = ' + bar);
rWin.alert('bar.size = ' + bar.size);
rWin.alert('bar.theDummy = ' + bar.theDummy);
rWin.alert('bar.theLastVar = ' + bar.theLastVar);
//rWin.alert('dummy = ' + dummy); //dummy was not exported so it will throw this error: "WARN addons.xpi: Exception running bootstrap method startup on Bootstrap-JSM@jetpack: ReferenceError: dummy is not defined (resource://gre/modules/XPIProvider.jsm -> jar:file:///C:/Documents%20and%20Settings/blah%20blah/Application%20Data/Mozilla/Firefox/Profiles/de83bb0q.default/extensions/Bootstrap-JSM@jetpack.xpi!/bootstrap.js:16)"
//END EXAMPLE
}
 
function shutdown(aData, aReason) {
if (aReason == APP_SHUTDOWN) return;
Cu.unload(chromeModulesPath + '/helloWorld.jsm');
//we get rid of it here, of course on shutdown of our
//addon it will be unloaded, however
//if helloWorld.jsm was imported in another privelaged scope it will
//persist there, until restart of browser.
//after running unload however, all instances of helloWorld.jsm can now be deleted? (im not sure about this last line)
}
 
function install() {}
 
function uninstall() {}
 
 
 
/* //do this if want to make it a resource uri instead of a chrome (chrome://bootstrap-jsm/content/hellowWorld.jsm)
// Import Services.jsm unless in a scope where it's already been imported
Components.utils.import('resource://gre/modules/Services.jsm');
 
var resProt = Services.io.getProtocolHandler('resource')
.QueryInterface(Components.interfaces.nsIResProtocolHandler);
 
var aliasFile = Components.classes['@mozilla.org/file/local;1']
.createInstance(Components.interfaces.nsILocalFile);
aliasFile.initWithPath('/some/absolute/path');
 
var aliasURI = Services.io.newFileURI(aliasFile);
resProt.setSubstitution('myalias', aliasURI);
 
// assuming the code modules are in the alias folder itself
*/
chrome.manifest
1
content bootstrap-jsm ./
helloWorld.jsm
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
//https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/
var EXPORTED_SYMBOLS = ['foo', 'bar'];
 
function foo() {
return 'foo';
}
 
var dummy = 'dummy is a string';
 
var bar = {
name: 'bar',
size: 3,
theDummy: dummy,
theLastVar: lastVar //when you import this jsm and try to get bar.theLastVar you will find that it is 'undefined', this is because 'lastVar' was not defined at the time this object was created
};
 
var lastVar = 'this is the last var its a string';
install.rdf
XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>Bootstrap-JSM@jetpack</em:id>
<em:version>initial</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:unpack>false</em:unpack>
 
<!-- Firefox -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>7.0</em:minVersion>
<em:maxVersion>27.0</em:maxVersion>
</Description>
</em:targetApplication>
 
<!-- Front End MetaData -->
<em:name>Bootstrap JSM</em:name>
<em:description>Template for how to create a JSM module.</em:description>
<em:creator>Noitidart</em:creator>
<em:contributor>Pat for Icon</em:contributor>
<em:optionsType>2</em:optionsType>
</Description>
</RDF>

README

Why chrome and why not resource?

At least as of Firefox 27.0.1, we cannot use resources in bootstrap.js, if we had put in our chrome.manifest file this code:

resource bootstrap-jsm ./

It would give us this error:

Bootstrapped manifest not allowed to use 'resource' directive.

Important things to learn in each commit

Revision 1

It's bugged don't look at it.

Revision 2

Fixed. The problem was the path in the manifest file was wrong. So download XPI and install it then import helloWorld.jsm like this:

Cu.import('chrome://bootstrap-jsm/content/helloWorld.jsm');

To demonstrate that theLastVar is undefined in the bar object because var lastVar was defined after that object do the following:

  • Open Scratchpad
  • Go to Environment menu and pick Browser
  • Import the module and alert bar.theLastVar, see code below
Cu.import('chrome://bootstrap-jsm/content/helloWorld.jsm');
Services.wm.getMostRecentWindow(null).alert(bar.theLastVar);
  • You will see that it alerts undefined

Revision 3

I put the example into the bootstrap file. It was important because it shows you cannot import the JSM module until startup() or after startup.

You can still do the experiment mentioned in Revision 2 section as JSM files can be imported anywhere.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.