title: Can I load custom jsm modules in bootstrap.js of a restartless add-on?
body: <p>I'm trying to load a custom module in a restartless add-on, using the following:</p>
  
  <p><strong>chrome/content/modules/Test.jsm</strong>:</p>
  
  <pre><code>var EXPORTED_SYMBOLS = [ 'Test' ];
  
  let Test = {};
  </code></pre>
  
  <p><strong>chrome.manifest</strong>:</p>
  
  <pre><code>content   test  chrome/content/
  </code></pre>
  
  <p><strong>bootstrap.js</strong>:</p>
  
  <pre><code>const Cu = Components.utils;
  
  // Tried this first, but figured perhaps chrome directives aren't loaded here yet
  // let test = Cu.import( 'chrome://test/modules/Test.jsm', {} ).Test;
  
  function install() {
    let test = Cu.import( 'chrome://test/modules/Test.jsm', {} ).Test;
  }
  function uninstall() {
    let test = Cu.import( 'chrome://test/modules/Test.jsm', {} ).Test;
  }
  function startup() {
    let test = Cu.import( 'chrome://test/modules/Test.jsm', {} ).Test;
  }
  function shutdown() {
    let test = Cu.import( 'chrome://test/modules/Test.jsm', {} ).Test;
  }
  </code></pre>
  
  <p>However, I get the following types of WARN messages (this one was for <code>shutdown()</code>, but basically identical for all functions and in the earlier attempt in the global scope):</p>
  
  <blockquote>
    <p>1409229174591 addons.xpi  WARN    Exception running bootstrap method
    shutdown on test@extensions.codifier.nl: [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/addons/XPIProvider.jsm ->
    file:///test/bootstrap.js :: shutdown :: line 21"  data: no] Stack
    trace: shutdown()@resource://gre/modules/addons/XPIProvider.jsm ->
    file:///test/bootstrap.js:21 &lt;
    XPI_callBootstrapMethod()@resource://gre/modules/addons/XPIProvider.jsm:4232
    &lt;
    XPI_updateAddonDisabledState()@resource://gre/modules/addons/XPIProvider.jsm:4347
    &lt;
    AddonWrapper_userDisabledSetter()@resource://gre/modules/addons/XPIProvider.jsm:6647
    &lt; uninstall()@extensions.xml:1541 &lt; oncommand()@about:addons:1 &lt;
    </p>
  </blockquote>
  
  <p>Are <code>chrome.manifest</code> directives not yet available in <code>bootstrap.js</code>? Or is what I am attempting some kind of security violation, perhaps? Or am I simply doing something trivially wrong?</p>
  
  <hr>
  
  <p>What I was hoping to achieve, is that I could do something like the following:</p>
  
  <p><strong>chrome/content/modules/Test.jsm</strong>:</p>
  
  <pre><code>var EXPORTED_SYMBOLS = [ 'Test' ];
  
  let Test = {
      install: function( data, reason ) {
      },
  
      /* etc */
  
      bootstrap: function( context ) {
          context.install = this.install;
          context.uninstall = this.uninstall;
          context.startup = this.startup;
          context.shutdown = this.shutdown;
      }
  }
  </code></pre>
  
  <p><strong>bootstrap.js</strong>:</p>
  
  <pre><code>const Cu = Components.utils;
  Cu.import( 'chrome://test/modules/Test.jsm' );
  Test.bootstrap( this );
  </code></pre>
  
  <p>Perhaps it's a bit over the top to begin with, but I just kind of like the idea of hiding implementations in modules and/or objects and keeping <code>bootstrap.js</code> super clean.</p>
  
  <p>If you happen to have suggestions on how to achieve this by other means: I'm all ears.</p>