Search code examples
javascriptfirefox-addonfirefox-addon-sdkjsm

Import .jsm file in Firefox Extension (with add-on sdk)


I'm trying to import a .jsm file (from This github) called "WebSocketServer.jsm" in my Firefox extension. The situation in the follow:

  • The .jsm file is in a directory called modules with this path:

root_of_extension/modules/WebSocketServer.jsm

  • I've added to my chrome.manifest file this line:

resource external_components modules/

  • I've insert in my code the commend to import the file:

Cu.import("resource://external_components/WebSocketServer.jsm");

The problem is that from console I see the following error

console.error: 
Object
- message = Component returned failure code: 0x80070057 (NS_ERROR_ILLEGAL_VALUE) [nsIXPCComponents_Utils.import]
- fileName = undefined
- lineNumber = 6
- stack = @undefined:6:undefined|CuddlefishLoader/options<.load@resource://gre/modules/commonjs/sdk/loader/cuddlefish.js:129:9|run@resource://gre/modules
/commonjs/sdk/addon/runner.js:149:1|startup/<@resource://gre/modules/commonjs/sdk/addon/runner.js:113:7|resolve@resource://gre/modules/commonjs
/sdk/core/promise.js:118:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|then@resource://gre/modules/commonjs/sdk/core/promise.js:153:9|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:118:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|then@resource://gre/modules/commonjs/sdk/core/promise.js:153:9|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:185:11|readAsync/<@resource://gre/modules/commonjs/
sdk/net/url.js:49:9|NetUtil_asyncOpen/<.onStopRequest@resource://gre/modules/NetUtil.jsm:137:17|
- toString = function () /* use strict */ toString

Line 6 in the "Cu.import" line. Do you have any ideas?


Solution

  • Here is a solution I just tested.

    First the structure:

    $ ls -lR
    total 8
    drwxr-xr-x  3 maierman  staff  102 23 Jul 15:45 data
    drwxr-xr-x  3 maierman  staff  102 23 Jul 15:47 lib
    -rw-r--r--  1 maierman  staff  164 23 Jul 15:33 package.json
    
    ./data:
    total 40
    -rw-------  1 maierman  staff  17925 23 Jul 15:45 WebSocketServer.jsm
    
    ./lib:
    total 8
    -rw-r--r--  1 maierman  staff  874 23 Jul 15:47 main.js
    

    Now, main.js:

    const self = require("sdk/self");
    const {Cc, Ci, Cu} = require("chrome");
    
    const wssuri = self.data.url("WebSocketServer.jsm");
    
    Cu.import(wssuri);
    
    // Create an echo server
    var clients = [];
    var server;
    
    exports.onUnload = function() {
      try {
        server.close();
        clients.slice().forEach(function(c) {
          try {
            c.close();
          }
          catch (cex) {
            console.debug("Failed to disconnect client " + client, cex);
          }
        });
      }
      catch (ex) {
        console.debug("Failed to disconnect server", ex);
      }
      Cu.unload(wssuri);
    };
    
    server = new WebSocketServer(12345);
    server.onclient = function(client) {
      console.log(client + " connected");
      clients.push(client);
    
      client.onmessage = function(client, msg) {
        console.log(client + " message:" + msg);
        client.send(msg);
      };
    
      client.onclose = function(client) {
        console.log(client + " disconnected");
        clients = clients.filter(function(c) {
          return c != client;
        });
      };
    };
    server.connect();
    

    Also make sure to get the lastest version of WebSocketServer.jsm. I just noticed and fixed a bug where client disconnection is not handled properly (but that is unrelated to your question).

    And tested this by executing the following in a Scratchpad.

    var ws = new WebSocket("ws://localhost:12345");
    ws.onmessage = function(e) {
      console.log(e.data);
    };
    ws.onopen = function(e) {
      console.log("opened");
      ws.send("hello, world!");
    };
    ws.onerror = ws.onclose = function(e) {
      console.log(e.type);
    };