Skip to content

Commit

Permalink
Updated the modules specification with define() and without camelCase…
Browse files Browse the repository at this point in the history
… module identifiers and without require.paths
  • Loading branch information
kriskowal committed May 31, 2011
1 parent 0056dc7 commit 5d62837
Showing 1 changed file with 121 additions and 81 deletions.
202 changes: 121 additions & 81 deletions modules/specification.md
@@ -1,99 +1,139 @@

This specification addresses how modules should be written in order to
be interoperable among a class of module systems that can be both client
and server side, secure or insecure, implemented today or supported by
future systems with syntax extensions. These modules are offered
privacy of their top scope, facility for importing singleton objects
from other modules, and exporting their own API. By implication, this
specification defines the minimum features that a module system must
provide in order to support interoperable modules.


Require
-------

1. ``require`` is a Function
1. The ``require`` function accepts a module identifier.
1. ``require`` returns the exported API of the foreign module.
1. If there is a dependency cycle, the foreign module may not have
finished executing at the time it is required by one of its
transitive dependencies; in this case, the object returned by
``require`` must contain at least the exports that the foreign
module has prepared before the call to require that led to the
current module's execution.
1. If the requested module cannot be returned, ``require`` must
throw an error.
1. The ``require`` function may have a ``main`` property.
1. This attribute, when feasible, should be read-only, don't
delete.
1. The ``main`` property must either be undefined or be identical
to the ``module`` object in the context of one loaded module.
1. The ``require`` function may have a ``paths`` attribute, that is
a prioritized Array of path Strings, from high to low, of paths
to top-level module directories.
1. The ``paths`` property must not exist in "sandbox" (a
secured module system).
1. The ``paths`` attribute must be referentially identical in all
modules.
1. Replacing the ``paths`` object with an alternate object may
have no effect.
1. If the ``paths`` attribute exists, in-place modification of
the contents of ``paths`` must be reflected by corresponding
module search behavior.
1. If the ``paths`` attribute exists, it may not be an
exhaustive list of search paths, as the loader may
internally look in other locations before or after the
mentioned paths.
1. If the ``paths`` attribute exists, it is the loader's
prorogative to resolve, normalize, or canonicalize the paths
provided.

Module Context
--------------

1. In a module, there is a free variable ``require``, which conforms to
the above definiton.
1. In a module, there is a free variable called ``exports``, that is an
object that the module may add its API to as it executes.
1. modules must use the ``exports`` object as the only means of
exporting.
1. In a module, there must be a free variable ``module``, that is
an Object.
1. The ``module`` object must have a ``id`` property that is the
top-level ``id`` of the module. The ``id`` property must be
such that ``require(module.id)`` will return the exports object
from which the ``module.id`` originated. (That is to say
module.id can be passed to another module, and requiring that
must return the original module). When feasible this property
should be read-only, don't delete.
1. The ``module`` object may have a ``uri`` String that is the
fully-qualified URI to the resource from which the module was
created. The ``uri`` property must not exist in a sandbox.
This specification establishes a convention for creating a style of
reusable JavaScript modules and systems that will load and link those
modules.

* Modules are singletons.
* Modules have an implicitly isolated lexical scope.
* Loading may be eager in asynchronous loaders.
* Execution must be lazy.
* With some care, modules may have cyclic dependencies.
* Systems of modules may be isolated but still share the same context.
* Modules may be used both in browsers and servers.


Guarantees Made by Module Writers
=================================

1. A module must only read and write variables in its lexical scope.
1. A module must only assume that its lexical scope contains the free
variables ``require``, ``module``, ``exports``, and ``define``
beyond those defined by JavaScript. *What constitutes JavaScript is
beyond the scope of this specification and may vary with practical
limits on a module's portability.*
1. A module must only depend on specified behavior of the values
provided to its lexical scope.
1. All calls to ``require`` must be by name from lexical scope.
1. All calls to ``require`` must be given a single string literal as
the argument.
1. For interoperability with loaders that support the following cases,
modules must call ``define`` in their first and only module scope
statement.
* When modules must be **debugged when deployed** on a different
domain than the origin page (perhaps a CDN) in browsers that do
not support cross-origin HTTP request headers (CORS) or the
developer cannot configure the deployment server to provide CORS
headers. JavaScript that is deployed in a debuggable form will
suffer performance penalties since it would preclude
minification and bundling.
* modules must be debugged in browsers that do not support
``//@sourceURL`` comments **and** (a module build step **or**
module server that add ``define`` calls are not acceptable).
1. Within a ``define`` ``callback``, the variables ``require``,
``exports``, and ``module`` must use the corresponding values
provided as arguments to the callback instead of those received from
lexical scope.
1. The first argument, ``require``, to a ``define`` ``callback`` must
be named ``require``.


Guarantees Made by Module Interpreters
======================================

1. The top scope of a module must not be shared with any other module.
1. A ``require`` function must exist in a function's lexical scope.
1. The ``require`` function must accept a module identifier as its
first and only argument.
1. ``require`` must return the same value as ``module.exports`` in
the identified module, or must throw an exception while trying.
1. ``require`` may have a ``main`` property.
1. The ``require.main`` property may be read-only and
non-configurable.
1. The ``require.main`` property must be the same value as
``module`` in the lexical scope of the first module that
began executing in the current system of modules.
1. The ``require.main`` property must be the same value in
every module.
1. an ``exports`` object must exist in a function's lexical scope.
1. the ``exports`` object must initially be the same value as
``module.exports``.
1. A ``module`` object must exist in a function's lexical scope.
1. The ``module`` object must have an ``id`` property.
1. The ``module.id`` property must be a module identifier such
that ``require(module.id)`` must return the
``module.exports`` value when called in this or any module
in the same system of modules.
1. The ``module.id`` property may be read-only and
non-configurable.
1. The ``module`` object must have an ``exports`` property.
1. The ``module.exports`` property must initially be an empty
object.
1. The ``module.exports`` property must be writable and
configurable.
1. The ``module`` object may have a ``path`` URL relative to
``file:///``
1. The ``module`` object may have a ``directory`` URL relative to
``file:///``
1. The directory must be the directory containing the ``path``.
1. a ``define`` function must exist in a function's lexical scope.
1. ``define`` accepts a function ("callback") as its last argument.
1. ``callback`` accepts ``require``, ``exports``, and ``module``.
1. ``callback`` must be called with the corresponding values from
the module's lexical scope.
1. If ``callback`` returns a value other than ``undefined``, the
return value must be assigned to ``module.exports``.


Module Identifiers
------------------
==================

1. A module identifier is a String of "terms" delimited by forward
1. A module identifier is a string of "terms" delimited by forward
slashes.
1. A term must be a camelCase identifier, ``.``, or ``..``.
1. Module identifiers may not have file-name extensions like ``.js``.
1. Module identifiers may be "relative" or "top-level". A module
1. A term is either:
1. any combination of lower-case letters, numbers, and hyphens,
1. ``.``, or
1. ``..``
1. Module identifiers should not have file-name extensions like
``.js``.
1. Module identifiers may be "relative" or "resolved". A module
identifier is "relative" if the first term is ``.`` or ``..``.
1. Top-level identifiers are resolved off the conceptual module name
space root.
1. Relative identifiers are resolved relative to the identifier of the
module in which ``require`` is written and called.
1. Top-level identifiers are resolved relative to ``""``.
1. The ``require`` function in each module resolves relative
identifiers from the corresponding ``module.id``.
1. To resolve a module identifier,
1. an array of terms must be initialized to an empty array.
1. For each ordered term in some ordered module identifiers, from
left to right,
1. no action is taken for ``"."`` terms,
1. a term is popped off the end of the array for ``".."``
terms, and
1. the term is pushed on the end of the array for all other
terms.
1. The array of terms must be joined with forward slashes, ``"/"``
to construct the resulting "resolved" identifier.



Unspecified
-----------
===========

This specification leaves the following important points of
interoperability unspecified:

1. Whether modules are stored with a database, file system, or factory
functions, or are interchangeable with link libraries.
1. Whether a PATH is supported by the module loader for resolving
1. Whether a path is supported by the module loader for resolving
module identifiers.
1. Whether other arguments may be provided to ``define`` and how they
are interpreted.

0 comments on commit 5d62837

Please sign in to comment.