Guarantees Made by Module Writers
May 10, 2012 ยท View on GitHub
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
No requirement in this section implies that a module system must enforce that requirement. These are merely requirements that a module must satisfy in order to function in any module system.
-
A module must be encoded in UTF-8.
-
A module must only assume that its scope contains
require,exports, andmodulein addition to the globals provided by JavaScript.- Depending on any other values limits portability to engines that do not provide those values and will cause reference errors on those systems.
-
A module must consider that every object in its scope may be immutable.
-
Depending on the mutability of an object precludes the use of the module in a system that shares its global scope among mutually suspcious programs, like between mashups in a secured JavaScript context.
-
It may be acceptable to upgrade an object in scope (shim) if it does not provide the needed, specified behavior, but this will limit portability to secure contexts with legacy implementations.
-
-
A module must only depend on the specified behavior of values in scope.
- Depending on any extension to the specified behavior limits portability.
-
All calls to
requiremust be given a single string literal as the argument, or the value ofrequire.mainif it is defined.-
If the argument to
requireis not a string, the dependency cannot be discovered and asynchronously loaded before executing the module. This would limit portability to systems that read the text of a module to discover dependencies and load them asynchronously before execution, which is necessary for portability to browsers and other systems that only support asynchronous loading. -
require.mainis guaranteed to already have been loaded, so it is a reasonable exception to the rule that all dependencies must be discoverable without executing the module.
-
-
All calls to
requiremust be by the namerequire.- If
requiretakes on a different name, the dependency will not be discoverable without executing the module.
- If
-
All calls to
requiremust be given a module identifier as the argument.- Some module loaders may accept values that are not module identifiers. Depending on this behavior inside a module limits the portability of the module, particularly to systems that use packages to isolate the module identifier name space for a set of modules.
Guarantees Made by Module Interpreters
-
The top scope of a module must not be shared with any other module.
- All
vardeclarations in a module will only be accessible within that module and will not collide with declarations in other modules
- All
-
A
requirefunction must exist in a function's lexical scope.-
The
requirefunction must accept a module identifier as its first and only argument. -
requiremust return the same value asmodule.exportsin the identified module, or must throw an exception while trying. -
requiremay have amainproperty.-
The
require.mainproperty may be read-only and non-configurable. -
The
require.mainproperty must be the same value asmodulein the lexical scope of the first module that began executing in the current system of modules. -
The
require.mainproperty must be the same value in every module.
-
-
requiremust have aresolvefunction.-
resolveaccepts a module identifier as its first and only argument -
resolvemust return the resolved module identifier corresponding to the given module identifier relative to this module's resolved module identifier.
-
-
requiremust have anasyncfunction.-
asyncmust accept an identifier or an array of identifiers as its first argument.- A single identifier is equivalent to an array with a single identifier.
-
asyncaccepts an optionalcallbackfunction as its second argument. -
asyncaccepts an optionalerrbackfunction as its third argument. -
asyncmust callrequirefor each module identifier in order -
asyncmay wait for each module's transitively required modules to asynchronously load before callingrequire. -
If any
requirecall throws an exception, or if any module cannot be loaded before it is required,errbackmust be called with theErroras its argument. -
If every
requirecall returns,asyncmust callcallbackwith the respective exports for each module identifier as its arguments.
-
-
-
An
exportsobject must exist in a function's lexical scope.- the
exportsobject must initially be the same value asmodule.exports.
- the
-
A
moduleobject must exist in a function's lexical scope.-
The
moduleobject must have anidproperty.-
The
module.idproperty must be a module identifier such thatrequire(module.id)must return themodule.exportsvalue when called in this or any module in the same system of modules. -
The
module.idproperty may be read-only and non-configurable.
-
-
The
moduleobject must have anexportsproperty.-
The
module.exportsproperty must initially be an empty object. -
The
module.exportsproperty must be writable and configurable.
-
-
The
moduleobject may have alocationabsolute URL. -
The
moduleobject may have adirectoryabsolute URL.- The
directorymust be the directory containing thelocation.
- The
-
Module Identifiers
-
A module identifier is a string of "terms" delimited by forward slashes.
-
A term is either:
-
any combination of lower-case letters, numbers, and hyphens,
-
a single dot, "
.", or -
a double dot, "
..".
-
-
Module identifiers should not have file-name extensions like
.js. -
Module identifiers may be "relative" or "resolved". A module identifier is "relative" if the first term is
.or... -
Top-level identifiers are resolved relative to
"". -
The
requirefunction in each module resolves relative identifiers from the correspondingmodule.id. -
To resolve any path of module identifiers,
-
An array of terms must be initialized to an empty array.
-
For each module identifier in the path of identifiers,
-
Pop off the last term in the array, provided one exists.
-
For each term in a module identifier in order,
-
Take no action if the term is
".". -
Pop a term off the end of the array if the term is
"..". -
Push the term on the end of the array otherwise.
-
-
-
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:
-
Whether modules are stored with a database, file system, or factory functions, or are interchangeable with link libraries.
-
Whether
requireaccepts values that are not module identifiers as specified here.