Specifying path of included module

I’m trying to load a module from within addon code (not content script) that is compatible with CommonJS but requires a module whose path needs to be specified.

After reading through the documentation for toolkit/loader, I thought I could accomplish what I’m after by simply creating a custom Loader and specifying a modules export in its options. Like so:

let { Loader, Module, load } = require("toolkit/loader");
let self = require("sdk/self");

// `bar` is required by `foo`
let loader = Loader({
  modules: {
    "bar": require("./bar")
  }
});

let module = Module("foo", self.data.url("../lib/foo.js"));
load(loader, module);

And in foo, I simply require bar:

require("bar");  

For whatever reason, this approach doesn’t work. Maybe it requires the use of Cu.import or some such. The documentation is anything but clear.

I then took a different approach, one relying on specifying the paths attribute:

let self = require("sdk/self");
let loader = Loader({
  paths: {
    "bar": self.data.url("../lib/bar.js"),
  }
});

let module = Module("foo", self.data.url("../lib/foo.js"));
load(loader, module);

But now nothing pertaining to the SDK loads inside foo. For instance, the following fails:

require("sdk/timers")

Questions:

  1. how can I specify the path to a module that is included somewhere without that causing havoc?
  2. how can I retrieve the URL of an asset in the extension’s lib directory? I’m currently using require("sdk/self").data.url("../lib/asset"), as you can see above, but surely there is a better way?

Did this solution help out? -

That’s not a solution because:

  1. I started that topic on Stackoverflow (notice both usernames).
  2. I think my question makes it clear I understand how to use require.
  3. The question asks how to specify the path of a module dependency, which wasn’t answered.
  4. It isn’t even marked as solved.

Getting snippy with the people trying to help you? In two different places? Always a good start. Perhaps you should consider that you haven’t explained yourself well enough. You haven’t explained what on earth the directory structure is that you’re trying to load from. Or why. And you keep claiming you know how to use the SDK, but clearly you don’t or you wouldn’t be asking this question. For example, a Loader modifies the behaviour of require. Creating an invalid Loader breaks require, yet here you are, confused.

The paths property of Loader specifies location names, not file names. Full filenames are constructed from the path and the name of the module being loaded at a later stage. More complex filename resolution can be provided with a resolve function. Relative pathnames passed to require are first resolved relative to the caller module, and then using paths. Bear in mind that when you are calling from a module loaded using a relative path, then the path initially resolved will also be relative. Also remember that the name you pass to the require statement is usually the actual name of a file (eg. bar.js) and a path will be constructed that will end with that string.

So the question remains: do you really need to do all this? Can your module really not be resolved by the standard loader? To answer your second question, you generally don’t need to retrieve those paths because require takes care of it all for you.

1 Like

I have never claimed to know how to use the SDK and would describe my knowledge of the SDK as merely functional. As you rightly said, it is implied in my asking a question here (and SO) that I don’t know how to use the SDK. My claim was simply that "I understand how to use require". I do not know how to create a custom Loader though.

IMHO you have taken the right approach in challenging the implied stance of my question that all the information one needs to be able to answer it is there, and not assuming I’m a moron. Here’s some additional information:

  • The addon loads a module using require, let’s call it external.js, that isn’t aware it is being loaded into Firefox addon context and is merely compatible with CommonJS form.

  • external.js then loads a dependency module whose location it is unaware of. The onus is on the programmer to specify its path.

  • I cannot change the code in external.js. In addition, creating a copy of the module and hard-coding the path of its dependency is an option we’d like to avoid at all costs for obvious reasons.

  • external.js is in data/lib, thus outside of the addon’s root lib directory (in which main.js and others resides).

  • to further complicate things, and for reasons that are beyond the scope of this discussion, the module external.js depends upon and loads resides in the addon’s root lib directory.

The above then means that:

  1. I need to somehow specify the path of the module that external.js loads.

  2. Unless I am completely mistaken, this most likely means I need to create a custom loader or somehow access the settings of the active loader and specify the path of the dependency in question.

  3. Since the path of the dependency is inside the addon’s root lib directory, invoking require("sdk/self").data.url("../lib/the-dependency.js") to obtain its path is… convoluted. Again, I’m probably missing a trick here but it’d be so much better to invoke a method that returns the URL of the addon’s root path. Although, now that I think about it, it’s probably not possible since resource://extension-id/ points to the extension’s root directory and that seems to actually be the same as returned by require("sdk/self").data.url(""). Ugh.

I did mention on my SO post that the problems I encountered using a custom loader “seems to imply that additional initialisation of the Loader instance is required but I’ve no clue where to start”. Apologies for not updating the question.

Were you able to figure this out @miguelg? I don’t know if this might help - https://github.com/freaktechnik/jetpack-panelview/blob/master/docs/panelview.md

I just found that useufl, but I was doing something a bit different then you.