Permalink
Fetching contributors…
Cannot retrieve contributors at this time
69 lines (49 sloc) 2.29 KB

When you require a module the first time, Narwhal constructs a function from the text of the module and executes it with three named arguments:

  • require
  • exports
  • module

Narwhal memoizes the exports object before it calls the "module factory function" so it gets returned immediately if your module gets required by one of its deep dependencies. The exports object is what require returns. It also guarantees that, in a single system of modules, the module factory function only gets called once. However, Narwhal also exposes all of the machinery it uses to load and execute modules so you can:

  • create a new system of modules, a "sandbox",
  • create new module loaders,
  • share a module loader with any number of sandboxes to cut down on time wasted parsing modules repeatedly,
  • execute a module factory function with any named arguments at any time,
  • execute a module factory function with a one-time-use exports object, require function and, module object with any additional free variables.

Making a module subsystem is great for test scaffolding and eventually will be useful for partitioning secure subsystems and injecting dependencies into that system. Narwhal's module system's own testing scaffold uses this feature.

Calling a module with additional free variables is great for constructing domain specific languages. Jakefile, QUnit, or Bogart would be great use-cases for this feature.

To get a module factory function, call require.load(id). The module factory function takes one argument: an object that owns the named free variables to inject into the module's lexical scope.

foo.js:

return a + b;

bar.js:

require.load("foo")({a: 10, b: 20}) === 30

When you use "load", the module gets exactly the free variables you have given it. If you want require, exports, and module to exist in that scope, you must either inject them manually (which is somewhat involved), or you can use the require.once(id, scope) convenience function.

qux.js:

var ASSERT = require("assert");
ASSERT.equal(a + b, 30);

quux.js:

require.once("qux", {a: 20, b: 10});

Future topics:

  • require("sandbox")
  • require("loader")
  • load
  • require.loader
  • require.loader.resolve(id, baseId)
  • require.loader.find
  • require.paths
  • require.loader.loaders