Namespaced Style Code

In addition to supporting CommonJS modules, for historical reasons BladeRunnerJS also supports namespaced style modules, which we refer to as NamespacedJS modules. Although we'd ideally ideally recommend that you update your modules to use CommonJS instead, this may not always be feasible, and so this page hopes to document any issues unique to using NamespacedJS modules within BladeRunnerJS.

Sub-Realms

If you've started using sub-realms to help test your CommonJs modules, but your application continues to be dependent upon NamespacedJS modules too, then you will need to re-install all global module references after installing and un-installing each sub-realm.

For example, instead of writing this:

var subrealm;

beforeEach(function() {
  subrealm = realm.subrealm();
  subrealm.install();

  // defines go here...

  // requires go here...
});

afterEach(function() {
  subrealm.uninstall();
});

you should instead write this:

var subrealm;

beforeEach(function() {
  subrealm = realm.subrealm();
  subrealm.install();

  // defines go here...

  globalizeSourceModules();

  // requires go here...
});

afterEach(function() {
  subrealm.uninstall();
  globalizeSourceModules();
});

Circular Dependencies

The Fixing Circular Dependencies section of the browser-modules documentation describes how to overcome circular dependency issues you may run into. However, very little of the advice applies if you are using NamespacedJS modules since:

  1. You are unable to convert define-time dependencies into use-time dependencies.
  2. You can't control the order in which modules will be required, since this is controlled by the globalizeSourceModules() function.

For NamespacedJS modules, use-time dependencies are automatically promoted to post-export define-time dependencies, increasing the likelihood of circular dependency errors. Although this is technically wrong, it turns out to be useful as it makes it possible to work around BladeRunnerJS's inability to detect self-invoking and singleton modules.

The Singleton Module Pattern

To prevent BladeRunnerJS from incorrectly classifying the dependencies within self-invoking and singleton modules, we recommend the use of a singleton-module-pattern described here. This pattern involves the conversion of any modules that look like this:

ns.Thingy = function() {
  // constructor code goes here...
};

ns.Thingy = new ns.Thingy();

into a distinct class-module and a singleton-module, where the class-module looks like this:

ns.ThingyClass = function() {
  // constructor code goes here...
};

and where the singleton-module looks like this:

ns.Thingy = new ns.ThingyClass();

This pattern has the additional advantage that it makes it possible to test the underlying class that was used to create the singleton.

Globalization Block Ordering

BladeRunnerJS automatically orders the globalization-block to reduce the chance of circular dependencies becoming problematic. This is really helpful given that it's not possible to mark dependencies as being use-time dependencies, but is also limiting since the algorithm used for ordering is best-effort only, and doesn't correctly solve all dependency graphs.

In cases where problems still remain even after making use of the singleton-module-pattern, the final option is to hide dependencies from BladeRunnerJS completely.

For example, this module:

pkg1.pkg2.SomeClass = function() {
  this.obj = new pkg1.pkg2.OtherClass();
};

can be re-written as:

pkg1.pkg2.SomeClass = function() {
  this.obj = new pkg1['pkg2'].OtherClass();
};

This is akin to converting the dependency to a use-time dependency, except that the dependency is no longer known about whatsoever, so won't work if pkg1/pkg2/OtherClass isn't also a dependency of some other module, or modules.