Modules/Transport/E

From CommonJS Spec Wiki
Jump to: navigation, search

STATUS: STRAWMAN

Implementations
[[Implementations/FlyScript|]]

This specification addresses how modules can be dynamically added to the module namespace of the current runtime environment.

Background

When deploying modules for use in the browser it is generally undesirable to load each module independantly, as this would require a separate HTTP request for each module. Furthermore, browser programming conventions dictate that functionally indepedant programs should continue to work when concatenated with other programs.

This specification presents an API for dynamic module registration which will allow multiple modules to be deployed in a single script file, and which can be concatenated with other scripts without loss of functionality.

Goals

  • Support for dynamic module registration must be feature-testable.
  • Support for dynamic module registration must be available outside of any module scope.
  • Expressions which result in dynamic module registration must be independant and self-contained.
  • Global variable names should be chosen to minimize conflict with existing programs, while still providing readability.
  • The number of global names introduced by this and other specifications should be minimized.

Contract

  1. In an environment which supports dynamic module registration, there exists a global variable named "CommonJS".
  2. The "CommonJS" global variable must have a property "attachModule" which is a function.
  3. The "attachModule" function must accept three arguments:
    1. A "module ID", which is a top-level module identifier.
    2. A "dependency array", which is an Array containing relative or top-level module identifiers.
      1. Relative module identifiers in the "dependency array" are resolved relative to the "module ID".
      2. The environment may use the contents of the "dependency array" to ensure that the module's dependencies are avaiable prior to executing the "module factory".
    3. A "module factory", which may be a function, a string, or an object.
      1. If the "module factory" is an object, then the module's exports are set to that object.
      2. If the "module factory" is a string, then it is converted to a function with "require", "exports", and "module" as the first three formal parameters.
      3. If the "module factory" is a function or has been converted to a function from a string:
        1. The function must be called with the actual parameters "require", "exports", and "module" corresponding to the free variables defined in module's scope.
        2. When called, the function must initialize the module's exports.
        3. If a value is returned from the function such that the abstract operation ToBoolean(value) equals true, then the module's exports are set to that value.
  4. When the "attachModule" function is executed, a module with the specified top-level identifier must be created in the current module namespace.
  5. If a module with the specified top-level identifier already exists, then "attachModule" has no effect.

Sample Code

Registering a module dynamically

CommonJS.attachModule("a", [], function(require, exports, module)
{
    exports.foo = "bar"; 
});

Registering a module which has a dependency and returns a value

CommonJS.attachModule("a", ["./b"], function(require)
{
    var b = require("./b");
    return { foo: "bar", fooB: b.foo };
});

Registering a module with an object factory

CommonJS.attachModule("some-data", [],
{
    foo: "bar"
});

Registering a module with a string factory

CommonJS.attachModule("a", [], "exports.foo = 'bar';");

Registering jQuery as a CommonJS module from within the jQuery core

try { CommonJS.attachModule("jquery/1.5", [], function() { return jQuery; }); }
catch (x) { /* Not Supported */ }